Errors and Failure Modes
General format
User-facing CLI errors are written to stderr in the format:
error: <message>The command exits with a non-zero exit code.
Common blocking situations
| Situation | What it means | What to do |
|---|---|---|
Untracked file conflicts with remote during sync | a file in skills/, mcp/, or loadouts/ matches by name a file from remote | rename the file, publish it via aiman push, or use --force (the conflicting file will be deleted) |
Remote is ahead during push | the published state has moved forward | run aiman sync |
| Git history has diverged | AIM cannot safely choose a state | restore Git manually |
| AI environment not found | adapter could not find the base dir | set the path in aim.local.yaml |
| MCP env not set | a required variable is missing | enter during sync or add to aim.local.yaml |
| Invalid Skill | missing frontmatter, missing name, missing description, or empty body | fix skills/<name>.md |
| Invalid MCP Item | missing required field or invalid YAML | fix mcp/<name>.yaml |
No active repository during import | no inventory repository is selected | run aiman init <url> or aiman switch <path> |
Invalid item name during import | the <name> argument is empty, contains /, \, .., or control characters, or is longer than 255 characters | pass the item name, not a file path; files are added with aiman add |
MCP server with an unsupported transport during import mcp | the server is declared as http/sse or via url instead of command | AIM manages stdio servers only; keep such a server configured in the environment by hand |
Loadout not found during apply --loadout | loadouts/ has no file and no name field with that name | check the name; the available ones are listed in the hint |
| Invalid loadout | missing name, empty items, wrong reference prefix, or invalid YAML | fix loadouts/<name>.yaml |
Broken loadout reference during push | skill:<name> or mcp:<name> does not exist in the inventory | fix items or add the item to the inventory |
Pin points to a nonexistent loadout during sync | the loadout pinned via apply --pin was deleted, renamed, or is missing from the current repository | aiman apply --default or aiman apply --unpin to clear the pin, or restore/rename the loadout back |
Flag conflict in apply (--pin/--default/--unpin) | an incompatible combination of pin flags | use the flags individually — see CLI Reference |
| No access to remote | Git cannot read or write the repository | check network, credentials, and permissions |
Import errors
All three errors below occur before anything is written to disk: the inventory and the AI environments are left untouched.
No active inventory repository — aiman import skill and aiman import mcp never write to the current directory:
error: no active inventory repository; run 'aiman init' firstConnect a repository (aiman init <url>) or switch to an existing one (aiman switch <path>). The check also runs with the --print flag.
Invalid item name — the name is validated before the write path is built, so an import cannot escape the inventory repository:
error: invalid item name "../evil": must not contain "/" or "\"An empty name, ., .., names containing / or \, absolute paths, control characters, and names longer than 255 characters are all rejected. The command argument is the name of the item in the AI environment, not a path to a file.
The MCP server uses an unsupported transport — only stdio servers (those that define a command) can be imported:
error: MCP server "remote-tool": unsupported transport "http" (only stdio servers can be imported)Such a server is no longer created in the inventory as an empty stub: the command stops and names the reason. Other servers in the same config are imported as usual.
Loadout errors
Loadout not found (aiman apply --loadout):
hint: available loadouts: dev, docs
error: loadout "ghost" not found in loadouts/The hint line is printed when there are between one and five valid loadouts, and it lists name field values, not filenames. A missing or empty loadouts/ directory produces the same not-found error, but without the hint.
Invalid loadout — apply --loadout stops at the first error:
error: loadout "empty": items: cannot be emptyaiman push prints all format errors across every file in loadouts/ at once, with the full path to each file:
error: /home/user/aim-inventory/loadouts/empty.yaml: items: cannot be emptyBroken reference to an inventory item (aiman push, blocks publishing):
error: loadout "Documentation Work" references unknown skill "missing-skill"
hint: check loadouts/documentation-work.yaml → itemsAny failed validation ends with the summary line error: validation failed — fix errors before publishing.
The same situation during apply --loadout is a warning, not an error: the item is skipped and the apply continues:
warning: loadout "dev": no valid inventory item for skill:ghost (skipped)Loadout warnings that block neither push nor apply: a missing description, and a filename that does not match the normalized name.
Pinned loadout
The pin points to a loadout that no longer exists — aiman sync stops without touching AI environments or updating synced_hash:
error: pinned loadout "documentation-work" not found in inventoryThis error is distinct from loadout "X" not found in loadouts/, which apply --loadout returns when no pin is involved — the wording differs deliberately, so the source of the error is easy to tell apart in logs. Causes: the loadout was renamed or deleted, the repository published a newer state from another machine, or aiman switch moved to a repository that never had a loadout with that name. To recover:
- clear the pin without applying anything:
aiman apply --unpin; - or go back to the full inventory:
aiman apply --default; - or restore/rename the loadout under the expected name in the inventory repository and retry
aiman sync.
Flag conflicts for apply --pin / --default / --unpin are checked before the inventory is read, before dispatching into apply:
| Combination | Error |
|---|---|
--pin without --loadout | error: --pin requires --loadout <name> |
--default + --loadout | error: --default and --loadout are mutually exclusive |
--default + --pin | error: --pin is redundant with --default |
--unpin combined with --loadout, --pin, or --default | error: --unpin does not apply — combine only alone |
For the full description of the flags, see the CLI Reference; for the config field, see the Config Reference.
--dry-run
For potentially destructive operations, run dry-run first:
aiman push --dry-run
aiman sync --dry-run
aiman apply --dry-run
aiman apply --loadout <name> --dry-runDry-run shows the plan without writing to Git, the inventory repository, or AI environments. For apply --loadout, make dry-run a habit: the D lines in the plan show what will be removed from your environments.
--force
aiman sync --force removes untracked files in skills/, mcp/, and loadouts/ that conflict by name with remote files, then applies the published state. Files without conflicts are always preserved.
Use this flag only if the conflicting files can be safely deleted. The deletion is permanent.