dagger/dagger · error

failed to encode spec: %w

Error message

failed to encode spec: %w

What it means

The engine failed to write the container's OCI runtime spec as the runc bundle config.json (json.NewEncoder(f).Encode(state.spec)). runc cannot start a container without a valid bundle config, so this aborts the container run.

Source

Thrown at engine/engineutil/executor_spec.go:1250

func (c *Client) runContainer(ctx context.Context, state *execState) (rerr error) {
	bundle := filepath.Join(c.ExecutorRoot, state.id)
	if err := os.Mkdir(bundle, 0o711); err != nil {
		return err
	}
	state.cleanups.Add("remove bundle", func() error {
		return os.RemoveAll(bundle)
	})

	configPath := filepath.Join(bundle, "config.json")
	f, err := os.Create(configPath)
	if err != nil {
		return err
	}
	defer f.Close()

	if err := json.NewEncoder(f).Encode(state.spec); err != nil {
		return fmt.Errorf("failed to encode spec: %w", err)
	}
	f.Close()

	lg := bklog.G(ctx).
		WithField("id", state.id).
		WithField("args", state.spec.Process.Args)
	if state.execMD != nil {
		if state.execMD.CallDigest != "" {
			lg = lg.WithField("call_id", state.execMD.CallDigest)
		}
	}
	if state.callerClientID != "" {
		lg = lg.WithField("caller_client_id", state.callerClientID)
	}
	if state.nestedClientMetadata != nil && state.nestedClientMetadata.ClientID != "" {
		lg = lg.WithField("nested_client_id", state.nestedClientMetadata.ClientID)
	}
	lg.Info("starting container")
	defer func() {

View on GitHub (pinned to 82ba2681db)

Solutions

  1. Check engine host disk space (df) — ENOSPC on the executor root is the most common cause
  2. Check the wrapped inner error to distinguish write failure from marshal failure
  3. Free space or move the engine's data root; restart the engine to clear stale bundles
  4. If it's a marshal error, check for non-serializable spec fields (custom builds)

Example fix

// diagnosis
// before (engine host)
df -h /var/lib/dagger
// after: free space or remount storage, then rerun the pipeline
Defensive patterns

Strategy: validation

Validate before calling

// Precheck on the engine host before starting work:
// stat -f -c '%a %T' <executor-root>  (free blocks/inodes)
// alert if free space below threshold, e.g.:
if free, err := diskFree(executorRoot); err == nil && free < 1<<30 {
    return fmt.Errorf("insufficient disk (%d bytes free) for runc bundle", free)
}

Try / catch

// Go
if err := json.NewEncoder(f).Encode(state.spec); err != nil {
    var jerr *json.UnsupportedTypeError
    if !errors.As(err, &jerr) { // then it was a write error
        bklog.G(ctx).Errorf("config.json write failed (disk full?): %v", err)
    }
    return fmt.Errorf("failed to encode spec: %w", err)
}

Prevention

When it happens

Trigger: Encoding specs.Spec to the already-created config.json file errors. Since a plain *os.File encode only fails on write errors, this is typically ENOSPC/disk-full, I/O error, or a spec value that fails to marshal (rare).

Common situations: Engine host disk full (bundle dir on a full filesystem); storage backend errors; I/O failures on the engine's executor root mount.

Related errors


AI-assisted analysis of dagger/dagger@82ba2681db (2026-09-05). Data as JSON: /api/errors/1fea3484de6b9bd5. Report an issue: GitHub.