GoogleContainerTools/skaffold · error

unable to resolve tag for image: %s

Error message

unable to resolve tag for image: %s

What it means

TransitiveArtifactDependencies resolves a single artifact's dependency list, but first it asks the artifactResolver for the image tag that was assigned to the artifact's image name during the current build sequence. If no tag is registered for that image name, dependency computation cannot proceed and this error is thrown.

Source

Thrown at pkg/skaffold/graph/dependencies.go:70

	return &dependencyResolverImpl{cfg: cfg, artifactResolver: r, artifactGraph: g, cache: util.NewSyncStore[[]string]()}
}

type dependencyResolverImpl struct {
	cfg              docker.Config
	artifactResolver docker.ArtifactResolver
	artifactGraph    ArtifactGraph
	cache            *util.SyncStore[[]string]
}

func (r *dependencyResolverImpl) TransitiveArtifactDependencies(ctx context.Context, a *latest.Artifact) ([]string, error) {
	ctx, endTrace := instrumentation.StartTrace(ctx, "TransitiveArtifactDependencies", map[string]string{
		"ArtifactName": instrumentation.PII(a.ImageName),
	})
	defer endTrace()

	tag, ok := r.artifactResolver.GetImageTag(a.ImageName)
	if !ok {
		return nil, fmt.Errorf("unable to resolve tag for image: %s", a.ImageName)
	}

	deps, err := r.SingleArtifactDependencies(ctx, a, tag)
	if err != nil {
		endTrace(instrumentation.TraceEndError(err))
		return nil, err
	}
	for _, ad := range a.Dependencies {
		d, err := r.TransitiveArtifactDependencies(ctx, r.artifactGraph[ad.ImageName])
		if err != nil {
			endTrace(instrumentation.TraceEndError(err))
			return nil, err
		}
		deps = append(deps, d...)
	}
	return deps, nil
}

View on GitHub (pinned to a1189de023)

Solutions

  1. Verify the image name referenced in the artifact's `dependencies` exactly matches a defined artifact's `image` name in skaffold.yaml.
  2. Ensure all upstream artifacts are built before dependency resolution (run the full build pipeline rather than a single artifact).
  3. Check that the build didn't fail silently for the upstream artifact, leaving no tag registered.
  4. If invoked programmatically, confirm the artifactResolver you passed actually contains a mapping for every referenced image name.
Defensive patterns

Strategy: type-guard

Type guard

func tagResolved(resolver graph.ArtifactResolver, imageName string) bool {
	_, ok := resolver.GetImageTag(imageName)
	return ok
}

Try / catch

deps, err := r.TransitiveArtifactDependencies(ctx, a)
if err != nil && strings.Contains(err.Error(), "unable to resolve tag for image") {
	// artifact not built yet — skip dependency computation this cycle
	return nil // defer to next dev loop after build completes
}

Prevention

When it happens

Trigger: Calling TransitiveArtifactDependencies (via the resolver chain used by file watching and dependency hashing) for an artifact whose ImageName has not been built/tagged yet — e.g. an artifact referenced only as another artifact's dependency that hasn't completed its build, or an image name typo that matches no configured artifact.

Common situations: First iteration of `skaffold dev` before all artifacts are built; `skaffold build` with cross-artifact dependencies where a required artifact was skipped or failed; an artifact's image name in `dependencies` doesn't exactly match any defined artifact; custom resolvers/test harnesses passing an incomplete tag map.

Related errors


AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05). Data as JSON: /api/errors/add9d47111e62de3. Report an issue: GitHub.