argoproj/argo-workflows · error

dependency %q exited with non-zero code: %d

Error message

dependency %q exited with non-zero code: %d

What it means

In a container-set (emissary) workflow, a container that declares dependencies waits for each dependency's exitcode file and fails immediately if that dependency exited non-zero. This error propagates the dependency's exit code so the workflow step is marked Failed with a clear cause.

Source

Thrown at cmd/argoexec/commands/emissary.go:203

	for _, x := range template.ContainerSet.GetGraph() {
		if x.Name == containerName {
			for _, y := range x.Dependencies {
				logger.WithField("dependency", y).Info(ctx, "waiting for dependency")
				depDir := filepath.Clean(varRunArgo + "/ctr/" + y)
				// The dependency container will MkdirAll this too, but may not have
				// started yet; pre-create it so we can install an inotify watch on it.
				if err = os.MkdirAll(depDir, 0o777); err != nil {
					return fmt.Errorf("failed to create dependency dir: %w", err)
				}
				depExitPath := filepath.Join(depDir, "exitcode")
				code, waitErr := waitForDependencyExitCode(ctx, depExitPath, signals)
				if waitErr != nil {
					return waitErr
				}
				exitCode = code
				if exitCode != 0 {
					return fmt.Errorf("dependency %q exited with non-zero code: %d", y, exitCode)
				}
			}
		}
	}

	name, err = exec.LookPath(name)
	if err != nil {
		return fmt.Errorf("failed to find name in PATH: %w", err)
	}

	if os.Getenv("ARGO_DEBUG_PAUSE_BEFORE") == "true" {
		// User can create the file: /ctr/NAME_OF_THE_CONTAINER/before
		// in order to break out of the wait and release the container from
		// the debugging state.
		if waitErr := file.WaitForCreate(ctx, varRunArgo+"/ctr/"+containerName+"/before"); waitErr != nil {
			return fmt.Errorf("failed waiting for debug-pause-before marker: %w", waitErr)
		}
	}

View on GitHub (pinned to 35bff19146)

Solutions

  1. Look at the logs of the dependency container named in the error to find its actual failure
  2. Fix the dependency's command/image so it exits 0
  3. If the dependency may legitimately fail, remove it from Dependencies or make it tolerant (retry strategy / ignore exit code)
  4. Use `argo logs <pod> -c <dependency-container>` and the node's exit code in the UI to confirm

Example fix

// before
containers:
- name: main
  dependencies: [setup]
- name: setup
  image: busybox
  command: ["sh", "-c", "exit 1"]
// after
- name: setup
  image: busybox
  command: ["sh", "-c", "setup.sh || true"]
Defensive patterns

Strategy: retry

Validate before calling

// before submit, ensure dependency commands exit 0 in CI smoke tests
// e.g. docker run --rm <image> <dependency command> && echo ok

Try / catch

try { await runStep() } catch (e) { const m = e.message.match(/dependency "(.+?)" exited with non-zero code: (\d+)/); if (m) { const logs = await getPodLogs(pod, m[1]); throw new Error(`dep ${m[1]} failed (${m[2]}): ${logs}`) } throw e }

Prevention

When it happens

Trigger: A dependency container listed in x.Dependencies terminated with exit code != 0; waitForDependencyExitCode returned that code and runEmissary aborts before starting its own command.

Common situations: The dependency container crashed (application error, bad image, OOMKilled with non-zero exit), a sidecar/init-like container in a container set failed its setup, or the dependency's script had a bug.

Related errors


AI-assisted analysis of argoproj/argo-workflows@35bff19146 (2026-09-03). Data as JSON: /api/errors/82beef1a8beda3c8. Report an issue: GitHub.