skopeo icon indicating copy to clipboard operation
skopeo copied to clipboard

feature: Add proper error reporting for `inspect`

Open gabyx opened this issue 9 months ago • 8 comments

It would be very nice if skopeo would have proper error reporting interface. Especially on

skopeo inspect "docker:/..."

where its not clear where the image does not exist or there was an authentication error.

Its not clear how to deal with errors with skopeo in general and for tooling this is a problem.

I see the following errors on all skopeo commands:

  • exit code X: Authorization Error

on inspect:

  • exit code Y: -> manifest unknow or image not existing (currently its somehow exit 2 but its nowhere documented?)

gabyx avatar Apr 30 '25 06:04 gabyx

Thanks for reaching out. Please be more specific in what you mean by “proper”.

Are you talking about exit codes only? And, if relevant, what conditions?

(Ultimately, there’s very little that can fit into an 8-bit field. At some point, it would be easier to write a Go program a receive full Go types directly … to the extent those make any promises about reported error types, which is also somewhat limited.)

The current exit status 2 is documented in skopeo(1). But note the caveat there; there is no way to reliably distinguish an authentication failure from a missing image, in general. Some things just aren’t possible.

mtrmac avatar Apr 30 '25 09:04 mtrmac

Ah ok, jeah I mean only exit code: so you say the container registry API does not have a destinction in http response status codes between notfound and auth error? Strange? especially for the transport docker://

gabyx avatar May 03 '25 22:05 gabyx

It does have that distinction, but there have been registries which replied with “not found” to requests to read something the user (anonymous or authenticated) does not have the right to to access — I guess with the idea that even disclosing the existence of that name is disclosing private information.

mtrmac avatar May 05 '25 13:05 mtrmac

Ah, ok. Its just hard to know what maps to 2? Possibly anything? Also server error? Or only failures of Unauthorized/Notfound etc for that Inspect operations?

It just leads to code like this, but maybe there is no better way?

func checkIfExists(skopeo *skopeo.Context, dest string) (exists bool, err error) {
	log.Info("Checking if image already exists.")

	cmd := []string{"inspect"}
	cmd = append(cmd, dest)
	exists = true

	// When repository does not exist yet ->
	// we get exit code 1, an we need to handle it somehow.

	// The workaround below is really ugly and prone to break!
	resp, e := skopeo.GetCombinedWithEC(
		func(cmdError *exec.CmdError) error {
			if cmdError != nil && cmdError.ExitCode() == 2 {
				exists = false

				return nil
			}

			return cmdError
		},
		cmd...)

	if e != nil {
		if strings.Contains(resp, "invalid status code from registry 403") ||
			strings.Contains(resp, "requested access to the resource is denied") {
			// we have 403 which is ok, the registry does not yet exist.
			exists = false
		}

		return true, errors.AddContext(
			e,
			"could not check if image '%s' exists:\nstdout/err:\n%s",
			dest,
			resp,
		)
	}

	return exists, nil
}

gabyx avatar May 05 '25 17:05 gabyx

I’d expect the behavior to be stable for a given server (and server’s software version?). But writing a tool reliably working for any registry on the internet is difficult.

(To be explicit, nothing in Skopeo promises to continue to use the exact text invalid status code from registry 403 in error messages, and we did change error texts in the past.)

mtrmac avatar May 05 '25 17:05 mtrmac

@mtrmac : Jeah thats correct, its a dumb workaround =). I now understand that its kind of difficult to make it work in all cases. The tool is great though!

gabyx avatar May 05 '25 20:05 gabyx

As an example of the difficulty of doing something useful here, recently I have noticed:

% skopeo inspect docker://quay.io/libpod/alpine:nonexistenttag
FATA[0001] Error parsing image name "docker://quay.io/libpod/alpine:nonexistenttag": reading manifest nonexistenttag in quay.io/libpod/alpine: manifest unknown 
% skopeo inspect docker://quay.io/libpod/nonexistentrepo                     
FATA[0001] Error parsing image name "docker://quay.io/libpod/nonexistentrepo": reading manifest latest in quay.io/libpod/nonexistentrepo: unauthorized: access to the requested resource is not authorized 

mtrmac avatar May 28 '25 22:05 mtrmac

A friendly reminder that this issue had no activity for 30 days.

github-actions[bot] avatar Jun 28 '25 00:06 github-actions[bot]