GoogleContainerTools/skaffold · error
unable to create dependency graph: %w
Error message
unable to create dependency graph: %w
What it means
Wraps NewDependencyGraph failure when building the release dependency DAG from helm.releases in skaffold.yaml. The graph builder rejects cycles or invalid release definitions, so Deploy cannot order the releases.
Source
Thrown at pkg/skaffold/deploy/helm/helm.go:265
// Check that the cluster is reachable.
// This gives a better error message when the cluster can't be reached.
if err := kubernetes.FailIfClusterIsNotReachable(h.kubeContext); err != nil {
return fmt.Errorf("unable to connect to Kubernetes: %w", err)
}
childCtx, endTrace := instrumentation.StartTrace(ctx, "Deploy_LoadImages")
if err := h.imageLoader.LoadImages(childCtx, out, h.localImages, h.originalImages, builds); err != nil {
endTrace(instrumentation.TraceEndError(err))
return err
}
endTrace()
olog.Entry(ctx).Infof("Deploying with helm v%s ...", h.helmVersion)
dependencyGraph, err := NewDependencyGraph(h.Releases)
if err != nil {
return fmt.Errorf("unable to create dependency graph: %w", err)
}
levelByLevelReleases, err := dependencyGraph.GetReleasesByLevel()
if err != nil {
return fmt.Errorf("unable to get releases by level: %w", err)
}
var mu sync2.Mutex
nsMap := map[string]struct{}{}
manifests := manifest.ManifestList{}
concurrency := 1
if h.Concurrency != nil {
if *h.Concurrency == 0 {
concurrency = -1 // unlimited
} else {
concurrency = *h.Concurrency
}View on GitHub (pinned to a1189de023)
Solutions
- Inspect helm.releases in skaffold.yaml and remove the dependency cycle between chartDependency entries
- Ensure every chartDependency name matches an existing release's name
- Simplify to a linear dependency chain if unsure
Example fix
// before (skaffold.yaml)
releases:
- name: a
chartDependency: b
- name: b
chartDependency: a
// after
releases:
- name: a
- name: b
chartDependency: a Defensive patterns
Strategy: validation
Validate before calling
names := map[string][]string{}
for _, r := range releases {
for _, dep := range r.ChartDependency {
if dep == r.Name {
return fmt.Errorf("release %q depends on itself", r.Name)
}
names[dep] = append(names[dep], r.Name)
}
}
// DFS cycle check
todo := map[string]bool{}
done := map[string]bool{}
var visit func(string) error
visit = func(n string) error {
if done[n] { return nil }
if todo[n] { return fmt.Errorf("cycle at %s", n) }
todo[n] = true
for _, dep := range deps[n] { if err := visit(dep); err != nil { return err } }
todo[n] = false; done[n] = true
return nil
}
for n := range deps { if err := visit(n); err != nil { return err } } Prevention
- Keep chartDependency chains one-directional (leaf -> root)
- Lint skaffold.yaml with a cycle check in CI
- Rename releases via search-and-replace across all chartDependency references
When it happens
Trigger: Calling Deploy with two or more releases whose chartDependency references form a cycle (release A depends on B, B depends on A), or a dependency referencing a non-existent release name.
Common situations: Copy-pasting release blocks in skaffold.yaml and leaving mutual chartDependency entries; renaming a release without updating another release's chartDependency.
Related errors
- duplicate release name %s
- release %s depends on non-existent release %s
- cycle detected involving release %q
- unable to get releases by level: %w
- unable to expand %q: %w
AI-assisted analysis of GoogleContainerTools/skaffold@a1189de023 (2026-09-05).
Data as JSON: /api/errors/dea34e6e3548c97e.
Report an issue: GitHub.