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

  1. Inspect helm.releases in skaffold.yaml and remove the dependency cycle between chartDependency entries
  2. Ensure every chartDependency name matches an existing release's name
  3. 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

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


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