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
- Verify the image name referenced in the artifact's `dependencies` exactly matches a defined artifact's `image` name in skaffold.yaml.
- Ensure all upstream artifacts are built before dependency resolution (run the full build pipeline rather than a single artifact).
- Check that the build didn't fail silently for the upstream artifact, leaving no tag registered.
- 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
- Keep `dependencies` image names in sync with artifact `image` names
- Run the full build pipeline rather than single-artifact builds when using cross-artifact deps
- Verify upstream builds succeeded before computing dependency graphs
- In tests, always seed the resolver's tag map for every referenced image
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
- CONFIG_MULTI_IMPORT_PROFILE_CONFLICT_ERR
- executing template: %w
- writing build output: %w
- writing build output to file: %w
- executing build: %w
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/add9d47111e62de3.
Report an issue: GitHub.