Errors & exit codes

Every sunscreen error has three things: a numeric exit code, a stable string code, and an actionable next_step.

Exit codes

ExitCodeMeaning
0success
1unexpecteda bug — please report with RUST_BACKTRACE=1 output
2toolchain_missinga required external tool (anchor, solana, …) was not found
3invalid_configsunscreen.yml failed schema validation
4user_inputconflicting / ambiguous / unrecognized user request
5missing_workspaceno sunscreen.yml found upward from cwd
9plugin_runtimea plugin crashed, violated the sandbox, or returned a protocol error

Common error codes (string-level)

These are stable identifiers you can match on in scripts. Subset, full list lives in src/error.rs.

Toolchain (exit 2)

codenext_step
toolchain_missing.anchorInstall via AVM: cargo install --git https://github.com/coral-xyz/anchor avm --locked && avm install latest
toolchain_missing.solanash -c "$(curl -sSfL https://release.solana.com/stable/install)"
toolchain_missing.pnpmnpm i -g pnpm
toolchain_missing.cargo_build_sbfComes with the solana install — re-run the solana installer

Invalid config (exit 3)

codeTrigger
invalid_config.schemaTop-level shape doesn't match v1
invalid_config.field.<path>A specific field is wrong (path follows the YAML, e.g. invalid_config.field.plugins.0.version)
invalid_config.version_unknownYAML declares a version newer than this binary supports

User input (exit 4)

codeTrigger
user_input.path_conflictTarget directory exists (sunscreen refuses to overwrite without --force)
user_input.symbol_existsA scaffold target (instruction, account, …) is already defined
user_input.recipe_preflightA recipe's preflight detected conflicts
user_input.ambiguous_flagTwo flags conflict (e.g. --dry-run + --force)
user_input.semver--version argument isn't valid semver
network.rate_limitedFaucet returned 429
network.unreachableRPC didn't respond

Missing workspace (exit 5)

codeTrigger
missing_workspaceNo sunscreen.yml in cwd or ancestors

Plugin runtime (exit 9)

codeTrigger
plugin_runtime.protocolPlugin emitted invalid JSON-RPC
plugin_runtime.sandboxPlugin tried to write outside workspace or open a forbidden network connection
plugin_runtime.crashPlugin exited unexpectedly (non-zero, no response)
plugin_runtime.manifestPlugin manifest invalid or unreadable

next_step contract

Every error includes a next_step field — a short, imperative sentence telling you what to do. This is part of the stable surface (tested by tests/errors_contract.rs).

Human-readable form:

error: user_input.symbol_exists: instruction "create_post" already exists (exit 4)
next_step: Pass --force to overwrite, or pick a different name.

JSON form:

{
  "status": "error",
  "error": {
    "code": "user_input.symbol_exists",
    "message": "instruction \"create_post\" already exists",
    "next_step": "Pass --force to overwrite, or pick a different name"
  }
}

Reporting bugs

Exit 1 (unexpected) is a bug. Include in the issue:

  • sunscreen --version
  • The full command you ran
  • Output with RUST_BACKTRACE=1
  • sunscreen doctor --json