docker/compose · error
exit code %d
Error message
exit code %d
What it means
After a `sync_exec` watch trigger copies files into the container, Compose runs the configured command via the Docker exec API and inspects its result. This error means the exec'd process finished with a non-zero exit code — the command itself failed inside the container.
Source
Thrown at pkg/compose/watch.go:518
return err
}
// although the errgroup is not tied directly to the context, the operations
// in it are reading/writing to the connection, which is tied to the context,
// so they won't block indefinitely
if err := eg.Wait(); err != nil {
return err
}
execResult, err := t.s.apiClient().ExecInspect(ctx, execCreateResp.ID, client.ExecInspectOptions{})
if err != nil {
return err
}
if execResult.Running {
return errors.New("process still running")
}
if execResult.ExitCode != 0 {
return fmt.Errorf("exit code %d", execResult.ExitCode)
}
return nil
}
func (t tarDockerClient) Untar(ctx context.Context, id string, archive io.ReadCloser) error {
_, err := t.s.apiClient().CopyToContainer(ctx, id, client.CopyToContainerOptions{
DestinationPath: "/",
Content: archive,
CopyUIDGID: true,
})
return err
}
//nolint:gocyclo
func (s *composeService) handleWatchBatch(ctx context.Context, project *types.Project, options api.WatchOptions, batch []watch.FileEvent, rules []watchRule, syncer sync.Syncer) error {
var (
restart = map[string]bool{}
syncfiles = map[string][]*sync.PathMapping{}View on GitHub (pinned to ddc4b044b6)
Solutions
- Run the same exec command manually (`docker compose exec <svc> <cmd>`) to see the real failure output
- Fix the underlying command failure (build error, missing tool, bad path)
- Make the exec command resilient (e.g. a wrapper script that tolerates transient failures) if you don't want watch to stop
Defensive patterns
Strategy: try-catch
Try / catch
// When programmatically driving watch sync_exec, treat non-zero exits as command failures
err := watcher.SyncAndExec(ctx, svc, cmd)
var exitErr *exec.ExitError // or string-match "exit code %d" from compose
if err != nil && strings.Contains(err.Error(), "exit code") {
log.Printf("watch exec failed (command exited non-zero): %v", err)
// keep watching; don't crash the loop
} Prevention
- Test the exec command inside the image before wiring it into watch rules
- Use idempotent commands (reloader, make watch) that tolerate repeated runs
- Ensure binaries referenced by exec.command exist in the image's PATH
When it happens
Trigger: A file change fires a sync_exec rule; Compose creates an exec, waits for it, calls `ExecInspect`, and `ExitCode != 0`. Typical when the command is a test/build step that fails on the newly synced code.
Common situations: Running `make test` or a reloader command as the exec and the code change breaks the build; the command references a binary missing from the image's PATH; the command's working directory assumptions don't hold in the container.
Related errors
- can't watch with action %q on service %s without a command
- process still running
- --wait cannot be combined with --abort-on-container-exit, --
- --detach cannot be combined with --abort-on-container-exit,
- --no-build and --watch are incompatible
AI-assisted analysis of docker/compose@ddc4b044b6 (2026-08-15).
Data as JSON: /api/errors/da86e607251f98e8.
Report an issue: GitHub.