Skip to main content

Errors

Every raid failure carries a stable error code, a category that maps to an exit code, and an optional hint. Codes are part of raid's CLI contract: new codes ship additively; existing codes never change name or category across minor versions.

Exit codes

CodeCategoryMeaning
0successThe command completed successfully.
1genericAn unclassified failure. Used for raid internal bugs and uncategorised errors.
2configA profile, repo, or schema was invalid, missing required fields, or failed validation.
3taskA user task failed during execution (Shell exit, Script error, …).
4networkA clone, HTTP download, or other network-bound operation failed.
5not-foundA referenced profile, repo, environment, or command does not exist.

Subprocess exits (e.g. a Shell task's cmd: exit 7) preserve the subprocess's own exit code rather than mapping into the categories above. This matches the prior behaviour and means $? for raid <cmd> still reflects what the user's script returned.

Code table

CodeCategoryWhen you'll see it
UNKNOWNgenericAny error raid couldn't classify.
INTERNALgenericA raid logic error — file an issue.
GIT_NOT_INSTALLEDgenericgit not on PATH.
LOCK_FAILEDgenericCouldn't acquire ~/.raid/.lock (another raid process is holding it).
PROFILE_INVALIDconfigA profile failed schema validation.
PROFILE_FILE_READconfigCouldn't read or parse a profile file.
PROFILE_ALREADY_EXISTSconfigraid profile add collided with a registered profile.
REPO_INVALIDconfigA repo entry or repo raid.yaml is malformed.
CONFIG_INVALIDconfigThe root config (~/.raid/config.toml) is malformed.
CONFIG_LOAD_FAILEDconfigCouldn't load the root config.
SCHEMA_VALIDATION_FAILEDconfigA JSON Schema check failed.
ARG_INVALIDconfigA CLI argument failed validation.
TASK_FAILEDtaskA task failed during execution (generic).
TASK_SHELL_FAILEDtaskA Shell task exited non-zero.
TASK_SCRIPT_FAILEDtaskA Script task exited non-zero.
TASK_WAIT_TIMEOUTtaskA Wait task exceeded its timeout.
TASK_TEMPLATE_FAILEDtaskA Template task couldn't render or write.
TASK_GIT_FAILEDtaskA Git task (non-clone) failed.
CLONE_FAILEDnetworkgit clone returned non-zero.
TASK_HTTP_FAILEDnetworkAn HTTP task failed.
PROFILE_NOT_FOUNDnot-foundThe referenced profile is not registered.
PROFILE_NOT_ACTIVEnot-foundNo active profile is set.
PROFILE_FILE_MISSINGnot-foundA registered profile's file is missing on disk.
REPO_NOT_FOUNDnot-foundA repo name isn't in the active profile.
REPO_NOT_CLONEDnot-foundA repo path doesn't exist on disk (run raid install).
ENV_NOT_FOUNDnot-foundAn environment name isn't declared.
COMMAND_NOT_FOUNDnot-foundraid <cmd> referenced an unknown command.

JSON shape

--json is a persistent flag on rootCmd, so it works on any subcommand. When set, raid emits errors as a single line to stderr in this shape:

{
"error": {
"code": "REPO_NOT_CLONED",
"category": "not-found",
"message": "repository 'api-gateway' is not cloned at /Users/me/dev/api",
"hint": "Run `raid install` to clone all repos in the active profile.",
"repo": "api-gateway",
"path": "/Users/me/dev/api"
}
}
  • code and category are stable contracts. Use them for branching.
  • message is the same human-readable string that's printed to stderr in non-JSON mode. Treat it as informational, not stable.
  • hint is optional. When present it suggests what to try next.
  • Additional fields (repo, path, task, …) are code-specific structured details. They're additive — new fields may appear on a code in future minor versions without breaking parsers that ignore them.

MCP integration

When a mutating tool (raid_install, raid_env_switch, raid_run_task) fails, the MCP server emits the same structured payload as the {"error": {...}} shape above, wrapped with the tool name and any captured stdout/stderr:

{
"tool": "raid_install",
"code": "CLONE_FAILED",
"category": "network",
"message": "failed to clone repository 'api': exit status 128",
"output": "fatal: Could not read from remote repository.\n",
"repo": "api",
"url": "[email protected]:my-org/api.git"
}

This is returned via mcp.NewToolResultError(...) so MCP-aware clients see isError: true alongside the parseable payload.

Stability promise

Error codes are part of raid's public CLI contract:

  • A code's name and category never change across minor versions.
  • Codes are added additively. New codes can appear without breaking parsers, but existing codes are never repurposed.
  • The message text is informational and may be reworded.
  • New details fields can appear on existing codes; old fields are preserved.
  • Breaking changes (renames, category shifts, removals) require a major version bump and a deprecation period announced in What's New.