paperclipai/paperclip · critical · error

runtime-command.json has empty 'command'

Error message

runtime-command.json has empty 'command'

What it means

Returned by loadRuntimeCommandSpec in the agent-shim after the runtime-command.json file is found and parsed as JSON, but its 'command' field is the empty string (or missing, which decodes to ''). The shim then cannot exec.LookPath any binary, so it rejects the spec immediately; main.go prints the error and exits with code 2. Args, detectCommand, and installCommand are all optional; only command is required.

Source

Thrown at tools/agent-shim/runtime_command.go:26

type RuntimeCommandSpec struct {
	Command        string   `json:"command"`
	Args           []string `json:"args"`
	DetectCommand  string   `json:"detectCommand,omitempty"`
	InstallCommand string   `json:"installCommand,omitempty"`
}

func loadRuntimeCommandSpec(path string) (*RuntimeCommandSpec, error) {
	b, err := os.ReadFile(path)
	if err != nil {
		return nil, err
	}
	var spec RuntimeCommandSpec
	if err := json.Unmarshal(b, &spec); err != nil {
		return nil, err
	}
	if spec.Command == "" {
		return nil, errors.New("runtime-command.json has empty 'command'")
	}
	return &spec, nil
}

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Regenerate /run/paperclip/runtime-command.json with a non-empty command (the adapter binary name, e.g. 'claude', 'codex').
  2. Verify the writer that produces the spec resolves the adapter command before writing the file; fail fast upstream if it is empty.
  3. Inspect the spec file (cat the path) to confirm command is populated; the shim accepts absolute or PATH-resolved names.

Example fix

// before
// /run/paperclip/runtime-command.json
{ "command": "", "args": [] }

// after
{ "command": "claude", "args": [] }
Defensive patterns

Strategy: validation

Validate before calling

func validateRuntimeCommandSpec(spec *RuntimeCommandSpec) error {
    if spec == nil || spec.Command == "" {
        return errors.New("runtime-command.json requires a non-empty 'command'")
    }
    return nil
}
// call after loadRuntimeCommandSpec and before exec.LookPath.

Type guard

func isValidCommandSpec(s *RuntimeCommandSpec) bool {
    return s != nil && s.Command != ""
}

Try / catch

spec, err := loadRuntimeCommandSpec(*specPath)
if err != nil {
    if strings.Contains(err.Error(), "empty 'command'") {
        // regenerate the spec from the control plane, then retry once
        if regenErr := regenerateSpec(*specPath); regenErr != nil {
            fmt.Fprintf(os.Stderr, "[shim] regen failed: %v\n", regenErr)
            os.Exit(2)
        }
        spec, err = loadRuntimeCommandSpec(*specPath)
    }
    if err != nil {
        os.Exit(2)
    }
}

Prevention

When it happens

Trigger: The runtime-command.json written under /run/paperclip/ (or the -spec path) contains {"command":"","args":[...]} or is missing the command field entirely; the file is generated by a control-plane step that failed to fill in the adapter binary name.

Common situations: Control-plane bug that writes the spec before resolving the adapter command; a templated spec whose ${ADAPTER_COMMAND} variable expanded to empty; a hand-edited spec left with a blank command during debugging; a stale spec file left over from a previous, different adapter.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/ad647e3404049f78. Report an issue: GitHub.