# RFC-0005: Error Code Registry
> **Version:** 0.1.0 | **Status:** normative | **Phase:** test
---
## 1. Summary
---
## 2. Specification
### [RFC-0005:C-CODES] Error Code Table (Normative) <a id="rfc-0005c-codes"></a>
## Error Codes
**Canonical error code table:**
| E001 | `error[E001]: skill '<skill>' not found` | Skill resolution failed (no matching directory in any store) |
| E002 | `error[E002]: search index unusable; run 'skc build <skill>' to rebuild` | Index is missing, corrupt, or stale |
| E003 | `error[E003]: index hash collision; delete .skillc-meta/search-<hash16>.db and rebuild` | Index filename exists but belongs to different skill |
| E004 | `error[E004]: empty query` | Search query is empty or whitespace-only |
| E010 | `error[E010]: not a valid skill: '<path>' (missing SKILL.md)` | Directory exists but lacks SKILL.md |
| E011 | `error[E011]: missing frontmatter field '<field>' in SKILL.md` | SKILL.md lacks required `name` or `description` field entirely |
| E012 | `error[E012]: path escapes skill root: '<path>'` | Symlink or path traversal would escape skill directory |
| E020 | `error[E020]: section not found: '<section>'` | Gateway show command found no matching heading |
| E021 | `error[E021]: file not found: '<path>'` | Gateway open command target does not exist |
| E022 | `error[E022]: directory not found: '<path>'` | Gateway sources --dir target does not exist |
| E030 | `error[E030]: invalid query type: '<type>'` | Stats command received unknown query type |
| E031 | `error[E031]: invalid filter: '<message>'` | Stats command received malformed filter value |
| E040 | `error[E040]: no local logs found` | Sync command found no fallback logs to sync |
| E041 | `error[E041]: sync destination not writable: '<path>'` | Sync command cannot write to primary runtime directory |
| E042 | `error[E042]: sync source not readable: '<path>'` | Sync command cannot read from fallback log database |
| E050 | `error[E050]: skill '<skill>' already exists` | Init command target already has SKILL.md |
| E100 | `error[E100]: invalid option: '<message>'` | CLI parsing failed (unknown flag, missing value, etc.) |
| E300 | `error[E300]: <rule-id> <rule-name>: <message>` | Lint rule violation with error severity (see [RFC-0008](../rfc/RFC-0008.md)) |
| E999 | `error[E999]: <message>` | Internal error (IO, database, parsing, or other unexpected failures) |
## Warning Codes
**Canonical warning code table:**
| W001 | `warning[W001]: multiple matches for '<section>'; showing first` | Gateway show found multiple headings matching query |
| W002 | `warning[W002]: logging disabled; run 'skc sync' after session to merge logs` | Access logging failed, using fallback or disabled |
| W003 | `warning[W003]: stale local logs for '<skill>'; run 'skc sync' to upload` | Local fallback logs exist and are older than threshold |
| W300 | `warning[W300]: <rule-id> <rule-name>: <message>` | Lint rule violation with warning severity (see [RFC-0008](../rfc/RFC-0008.md)) |
**Warning behavior:**
- Warnings are printed to stderr but do NOT cause command failure
- Commands that emit warnings still exit with code 0
- Multiple warnings may be emitted per command invocation
## Resolution error hierarchy
When resolving a skill per [RFC-0007:C-RESOLUTION](../rfc/RFC-0007.md#rfc-0007c-resolution):
- **E010**: A directory was found (at the given path OR in project/global stores) but it lacks SKILL.md
- **E001**: No directory was found at the path AND no match in project/global stores
E010 is a more specific form of resolution failure. Use E010 when a directory exists but isn't a valid skill; use E001 when no directory is found at all.
## Lint diagnostics
Lint diagnostics (E300, W300) use a structured format that includes the rule ID from [RFC-0008:C-REGISTRY](../rfc/RFC-0008.md#rfc-0008c-registry):
```
<severity>[<code>]: <rule-id> <rule-name>: <message>
```
**Examples:**
- `error[E300]: SKL102 name-format: name contains invalid characters`
- `warning[W300]: SKL108 description-triggers: missing activation trigger`
- `warning[W300]: SKL401 no-orphans: orphaned file 'old-draft.md'`
The rule ID (SKLxxx) provides semantic detail; the diagnostic code (E300/W300) indicates severity. This separation allows adding new lint rules without modifying this RFC.
## Unified codes
The following codes are used across multiple RFCs:
- **E001/E010 (Skill resolution)**: All commands that resolve skills via [RFC-0007:C-RESOLUTION](../rfc/RFC-0007.md#rfc-0007c-resolution) MUST use E001 or E010 when resolution fails.
- **E002–E004 (Index/query)**: Errors for index state and query validation. Currently used by search; future commands with similar semantics should reuse these.
- **E012 (Path escape)**: Any command that validates paths MUST use E012 when a path would escape the skill root.
- **E040–E042 (Sync)**: Errors specific to the sync command for log synchronization.
- **E050 (Skill exists)**: Init command cannot overwrite existing skill.
- **E100 (Invalid option)**: All commands MUST use E100 for flag/option parsing failures.
- **E300/W300 (Lint)**: Skill authoring validation per [RFC-0008](../rfc/RFC-0008.md). Rule IDs (SKLxxx) provide specifics.
- **E999 (Internal)**: Unexpected failures (IO errors, database errors, parsing errors). These indicate bugs or environmental issues, not user errors.
- **W001 (Multiple matches)**: Gateway commands that find multiple matches.
- **W002 (Logging disabled)**: Access logging encountered errors.
- **W003 (Stale logs)**: Local fallback logs need syncing.
## Message format
All diagnostic messages MUST include the code in brackets:
- Errors: `error[EXXX]: <message>`
- Warnings: `warning[WXXX]: <message>`
This format enables:
- Machine parsing of diagnostic codes
- Easy searching in documentation
- Consistent user experience across commands
**Placeholder substitution:**
- `<skill>` — The skill name/path provided by the user
- `<path>` — File or directory path
- `<hash16>` — First 16 characters of SHA-256 hash
- `<field>` — Frontmatter field name
- `<section>` — Section heading text
- `<type>` — Query type string
- `<message>` — Contextual error details
- `<rule-id>` — Lint rule identifier (e.g., SKL102)
- `<rule-name>` — Lint rule name (e.g., name-format)
## Exit behavior
- **Errors**: Exit with status 1
- **Warnings**: Do not affect exit status (exit 0 if no errors)
Implementations MUST NOT use different exit codes for different error types.
## Adding new codes
New diagnostic codes MUST be added to this table via RFC amendment. Feature RFCs MUST NOT define new codes inline; they MUST reference this RFC and propose additions here.
**Exception:** Lint rules (SKLxxx) are defined in [RFC-0008](../rfc/RFC-0008.md) and use E300/W300 as their diagnostic codes. Adding new lint rules does not require amending this RFC.
**Reserved ranges:**
Error codes:
- E001–E010: Unified errors (skill resolution, index state, query validation, path safety)
- E011–E019: Compilation errors (RFC-0001)
- E020–E029: Gateway errors (RFC-0002)
- E030–E039: Analytics errors (RFC-0003)
- E040–E049: Sync errors (RFC-0007)
- E050–E059: Scaffolding errors (RFC-0006)
- E100–E199: CLI parsing errors (all commands)
- E200–E299: Reserved for network/remote errors
- E300: Lint errors (RFC-0008) — rule IDs provide specifics
- E999: Internal/unexpected errors
Warning codes:
- W001–W009: Gateway warnings
- W010–W019: Logging warnings
- W020–W029: Reserved for future use
- W300: Lint warnings (RFC-0008) — rule IDs provide specifics
*Since: v0.1.0*
### [RFC-0005:C-USAGE] Usage by Feature RFCs (Normative) <a id="rfc-0005c-usage"></a>
**Feature RFC requirements:**
Feature RFCs that define error behavior MUST:
1. **Reference this RFC** — Use `[RFC-0005](../rfc/RFC-0005.md)` or `[RFC-0005:C-CODES](../rfc/RFC-0005.md#rfc-0005c-codes)` when discussing error codes
2. **Use canonical codes** — Only use error codes defined in [RFC-0005:C-CODES](../rfc/RFC-0005.md#rfc-0005c-codes)
3. **Document applicability** — Specify which codes apply to which commands/conditions
4. **Not redefine messages** — Use the exact message templates from this RFC
**Example usage in feature RFCs:**
```markdown
**Error handling:**
See [RFC-0005:C-CODES](../rfc/RFC-0005.md#rfc-0005c-codes) for canonical error messages.
| Skill not found | E001 |
| Index unusable | E002 |
```
**Proposing new codes:**
To add a new error code:
1. Submit an amendment to this RFC
2. Include: code, message template, semantics, and reserved range justification
3. Update the canonical table in [RFC-0005:C-CODES](../rfc/RFC-0005.md#rfc-0005c-codes)
**Deprecating codes:**
Deprecated codes MUST remain in the table with a `(deprecated)` suffix in the Semantics column. They MUST NOT be removed to maintain backward compatibility.
*Since: v0.1.0*
---
## 3. Motivation
### [RFC-0005:C-OVERVIEW] Overview (Normative) <a id="rfc-0005c-overview"></a>
This RFC defines the **canonical diagnostic code registry** for `skillc`. All error and warning codes used across the CLI are defined here.
**Purpose:**
- Single source of truth for diagnostic semantics
- Consistent messages across commands
- Feature RFCs reference this registry instead of defining their own codes
**Scope:**
This RFC defines diagnostic codes and message templates. Per-command handling (which codes apply, when they're raised) remains in feature RFCs.
**Diagnostic levels:**
- **Errors** (`error[EXXX]`): Fatal conditions that prevent command completion. Exit code 1.
- **Warnings** (`warning[WXXX]`): Non-fatal conditions where command succeeds but with degraded behavior. Exit code 0.
**Design principles:**
- Exit code 1 for errors, 0 for warnings
- All diagnostics printed to stderr
- Human-readable messages with codes for documentation/search
*Since: v0.1.0*
---
## Changelog
### v0.1.0 (2026-01-30)
Initial release