# Waddling Error Sequence Conventions
**Version**: 0.2.0
**Status**: Active Convention
**Enforcement**: SHOULD (Recommended, not required)
---
## Overview
To maximize consistency across the Waddling ecosystem, certain sequence numbers have **reserved semantic meanings**. Projects **SHOULD** use these conventions when the error matches the semantic category.
This makes error codes instantly recognizable across ALL Waddling projects.
---
## Benefits
- ✅ **Instant Recognition**: `.001` always means "missing" across all projects
- ✅ **Cross-Project Learning**: Understand one project → understand all
- ✅ **Searchability**: Search for `.001` finds all "missing" errors ecosystem-wide
- ✅ **Documentation**: Document patterns once, reference everywhere
- ✅ **Predictability**: Users can guess error meanings from sequence alone
---
## Reserved Sequences (001-030)
These sequences have standardized semantic meanings across the Waddling ecosystem.
**Organization Pattern:**
- **001-010**: Input/Data Validation - Problems with provided data
- **011-020**: State/Lifecycle - Object state and lifecycle issues
- **021-030**: Resource/Storage - External resource access issues
### Input/Data Validation Errors (001-010)
| **001** | MISSING | Required parameter/argument not provided | Error |
| **002** | MISMATCH | Values don't match expected type/length | Error |
| **003** | INVALID | Format/validation failed | Error |
| **004** | OVERFLOW | Value too large for container/type | Error |
| **005** | UNDERFLOW | Value too small for requirement | Error |
| **006** | OUTOFBOUNDS | Index/value outside valid range | Error |
| **007** | DUPLICATE | Duplicate entry in collection/set | Error |
| **008** | DENIED | Permission/access denied | Error |
| **009** | UNSUPPORTED | Feature not supported | Error |
| **010** | DEPRECATED | Feature deprecated (warning) | Warning |
#### Examples
```rust
use waddling_errors::{ErrorCode, Severity};
// .001 = MISSING (input not provided)
const ERR_MISSING_PARAM: ErrorCode =
ErrorCode::new(Severity::Error, "API", "PARAM", 1);
// Error: [E.API.PARAM.001] Required parameter 'api_key' not provided
// .002 = MISMATCH (type/length mismatch)
const ERR_LENGTH_MISMATCH: ErrorCode =
ErrorCode::new(Severity::Error, "CRYPTO", "LENGTH", 2);
// Error: [E.CRYPTO.LENGTH.002] Expected 32 bytes, got 16
// .003 = INVALID (validation failed)
const ERR_INVALID_PATTERN: ErrorCode =
ErrorCode::new(Severity::Error, "PATTERN", "REGEX", 3);
// Error: [E.PATTERN.REGEX.003] Invalid regex syntax
// .007 = DUPLICATE (duplicate in collection)
const ERR_DUPLICATE_ENTRY: ErrorCode =
ErrorCode::new(Severity::Error, "DB", "ENTRY", 7);
// Error: [E.DB.ENTRY.007] Duplicate entry in unique constraint
// .010 = DEPRECATED
const WARN_DEPRECATED_API: ErrorCode =
ErrorCode::new(Severity::Warning, "API", "FUNC", 10);
// Warning: [W.API.FUNC.010] Function deprecated, use new_api() instead
```
---
### State/Lifecycle Errors (011-020)
| **011** | UNINITIALIZED | Object/resource not initialized | Error |
| **012** | ALREADYINIT | Already initialized (double-init) | Error |
| **013** | CLOSED | Resource closed/disposed | Error |
| **014** | CANCELLED | Operation was cancelled | Error |
| **015** | INPROGRESS | Operation already in progress | Blocked |
| **016** | NOTREADY | Not ready for operation | Error/Blocked |
| **017** | TIMEOUT | Operation timed out | Blocked/Error |
| **018** | STALE | Resource/state is stale/outdated | Warning/Error |
| **019** | *(reserved)* | Reserved for future use | - |
| **020** | *(reserved)* | Reserved for future use | - |
#### Examples
```rust
// .011 = UNINITIALIZED
const ERR_NOT_INITIALIZED: ErrorCode =
ErrorCode::new(Severity::Error, "ENGINE", "STATE", 11);
// Error: [E.ENGINE.STATE.011] Engine not initialized, call init() first
// .012 = ALREADYINIT
const ERR_ALREADY_INIT: ErrorCode =
ErrorCode::new(Severity::Error, "ENGINE", "STATE", 12);
// Error: [E.ENGINE.STATE.012] Engine already initialized
// .014 = CANCELLED
const ERR_CANCELLED: ErrorCode =
ErrorCode::new(Severity::Error, "TASK", "STATE", 14);
// Error: [E.TASK.STATE.014] Operation cancelled by user
// .015 = INPROGRESS
const BLOCKED_IN_PROGRESS: ErrorCode =
ErrorCode::new(Severity::Blocked, "TASK", "STATE", 15);
// Blocked: [B.TASK.STATE.015] Compilation in progress
// .017 = TIMEOUT
const ERR_OPERATION_TIMEOUT: ErrorCode =
ErrorCode::new(Severity::Error, "NET", "TIMEOUT", 17);
// Error: [E.NET.TIMEOUT.017] Operation timed out after 30s
```
---
### Resource/Storage Errors (021-030)
| **021** | NOTFOUND | Resource/entity not found in storage | Error |
| **022** | ALREADYEXISTS | Resource already exists (create conflict) | Error |
| **023** | CONFLICT | Version/data conflict (concurrent edit) | Error |
| **024** | LOCKED | Resource locked by another process | Blocked |
| **025** | CORRUPTED | Data corrupted/integrity check failed | Critical |
| **026** | EXHAUSTED | Resource exhausted (out of memory, etc.) | Critical/Error |
| **027** | UNAVAILABLE | Service/resource temporarily unavailable | Error/Blocked |
| **028** | UNREACHABLE | Network/host unreachable | Error |
| **029** | DISCONNECTED | Connection lost/dropped | Error |
| **030** | *(reserved)* | Reserved for future use | - |
#### Examples
```rust
// .021 = NOTFOUND (resource doesn't exist)
const ERR_FILE_NOT_FOUND: ErrorCode =
ErrorCode::new(Severity::Error, "IO", "FILE", 21);
// Error: [E.IO.FILE.021] File 'config.toml' not found
// .022 = ALREADYEXISTS (create conflict)
const ERR_FILE_EXISTS: ErrorCode =
ErrorCode::new(Severity::Error, "IO", "FILE", 22);
// Error: [E.IO.FILE.022] File already exists, cannot overwrite
// .023 = CONFLICT (version/data conflict)
const ERR_VERSION_CONFLICT: ErrorCode =
ErrorCode::new(Severity::Error, "DB", "VERSION", 23);
// Error: [E.DB.VERSION.023] Version conflict - concurrent modification
// .024 = LOCKED
const BLOCKED_MUTEX: ErrorCode =
ErrorCode::new(Severity::Blocked, "THREAD", "MUTEX", 24);
// Blocked: [B.THREAD.MUTEX.024] Resource locked, waiting...
// .025 = CORRUPTED
const CRIT_CORRUPTED: ErrorCode =
ErrorCode::new(Severity::Critical, "DATA", "INTEGRITY", 25);
// Critical: [C.DATA.INTEGRITY.025] Checksum failed - data corrupted
// .027 = UNAVAILABLE
const ERR_SERVICE_UNAVAILABLE: ErrorCode =
ErrorCode::new(Severity::Error, "API", "SERVICE", 27);
// Error: [E.API.SERVICE.027] Database temporarily unavailable
// .028 = UNREACHABLE
const ERR_HOST_UNREACHABLE: ErrorCode =
ErrorCode::new(Severity::Error, "NET", "HOST", 28);
// Error: [E.NET.HOST.028] Remote host unreachable
// .029 = DISCONNECTED
const ERR_CONNECTION_LOST: ErrorCode =
ErrorCode::new(Severity::Error, "NET", "CONN", 29);
// Error: [E.NET.CONN.029] Connection dropped unexpectedly
```
---
## Project-Specific Sequences (031-897)
Use for **domain-specific errors** that don't fit reserved semantic categories.
Projects have complete freedom in this range - use whatever makes sense for your domain.
#### Examples
```rust
const ERR_MAC_VERIFICATION: ErrorCode =
ErrorCode::new(Severity::Critical, "CRYPTO", "MAC", 31);
const ERR_HMAC_COMPUTE: ErrorCode =
ErrorCode::new(Severity::Error, "CRYPTO", "HMAC", 32);
const ERR_UNEXPECTED_TOKEN: ErrorCode =
ErrorCode::new(Severity::Error, "parser", "SYNTAX", 50);
const ERR_AST_MALFORMED: ErrorCode =
ErrorCode::new(Severity::Error, "parser", "AST", 51);
```
---
## Success/Completion Sequences (998-999)
| **998** | PARTIAL | Partial success (some items succeeded) | Success/Warning |
| **999** | COMPLETE | Full completion (all succeeded) | Success/Completed|
#### Examples
```rust
// .999 = COMPLETE
const SUCCESS_REDACTION: ErrorCode =
ErrorCode::new(Severity::Success, "REDACT", "DONE", 999);
// Success: [S.REDACT.DONE.999] Redaction completed successfully
const COMPLETE_COMPILE: ErrorCode =
ErrorCode::new(Severity::Completed, "BUILD", "DONE", 999);
// Completed: [K.BUILD.DONE.999] Compilation finished
// .998 = PARTIAL
const SUCCESS_PARTIAL: ErrorCode =
ErrorCode::new(Severity::Success, "BUILD", "RESULT", 998);
// Success: [S.BUILD.RESULT.998] 8/10 files compiled successfully
```
---
## Usage Guidelines
### ✅ DO: Use Reserved Sequences When Semantically Appropriate
```rust
// Good - follows convention
const ERR_MISSING_KEY: ErrorCode =
ErrorCode::new(Severity::Error, "CRYPTO", "KEY", 1); // .001 = MISSING
const ERR_TYPE_MISMATCH: ErrorCode =
ErrorCode::new(Severity::Error, "TYPE", "CHECK", 2); // .002 = MISMATCH
```
### ✅ DO: Use Project-Specific Sequences (031-897) for Domain Logic
```rust
// Good - domain-specific, no reserved semantic fits
const ERR_MAC_VERIFY: ErrorCode =
ErrorCode::new(Severity::Critical, "CRYPTO", "MAC", 31);
const ERR_PATTERN_COMPLEX: ErrorCode =
ErrorCode::new(Severity::Warning, "PATTERN", "PERF", 45);
```
### ❌ DON'T: Redefine Reserved Sequences with Different Meanings
```rust
// BAD - .001 should mean "missing", not "corrupted"
const ERR_CORRUPTED: ErrorCode =
ErrorCode::new(Severity::Error, "DATA", "CHECK", 1); // ❌ Wrong!
// CORRECT - use .025 for corruption
const ERR_CORRUPTED: ErrorCode =
ErrorCode::new(Severity::Critical, "DATA", "CHECK", 25); // ✅ Right!
```
### ✅ DO: Document Deviations
If you must deviate from conventions, document why:
```rust
// Using .050 instead of .001 because our "missing" has domain-specific meaning
const ERR_CUSTOM_MISSING: ErrorCode =
ErrorCode::new(Severity::Error, "CUSTOM", "LOGIC", 50);
```
---
## Quick Reference Table
| 001-010 | Input/Data validation | Missing param, mismatch, invalid, duplicate |
| 011-020 | State/Lifecycle | Uninitialized, closed, cancelled, timeout |
| 021-030 | Resource/Storage | Not found, already exists, locked, corrupted|
| 031-897 | Project-specific (free use) | Domain-specific logic |
| 898-997 | *(reserved for future)* | Reserved for future conventions |
| 998-999 | Success/completion (reserved) | Partial success, full completion |
---
## Cross-Project Examples
### Crypto Library
```rust
// Input validation (001-010)
const ERR_MISSING_SALT: ErrorCode = ErrorCode::new(Severity::Error, "CRYPTO", "SALT", 1);
const ERR_LENGTH_MISMATCH: ErrorCode = ErrorCode::new(Severity::Error, "CRYPTO", "LENGTH", 2);
const ERR_INVALID_KEY: ErrorCode = ErrorCode::new(Severity::Error, "CRYPTO", "KEY", 3);
// Resource errors (021-030)
const CRIT_MAC_CORRUPTED: ErrorCode = ErrorCode::new(Severity::Critical, "CRYPTO", "MAC", 25);
// Domain-specific (031+)
const ERR_HMAC_COMPUTE: ErrorCode = ErrorCode::new(Severity::Error, "CRYPTO", "HMAC", 31);
const SUCCESS_REDACT: ErrorCode = ErrorCode::new(Severity::Success, "REDACT", "DONE", 999);
```
### Compiler/Parser
```rust
// Input validation (001-010)
const ERR_MISSING_SEMICOLON: ErrorCode = ErrorCode::new("parser", "SYNTAX", 1);
const ERR_TYPE_MISMATCH: ErrorCode = ErrorCode::new("semantic", "TYPE", 2);
const ERR_INVALID_SYNTAX: ErrorCode = ErrorCode::new("parser", "SYNTAX", 3);
// State errors (011-020)
const ERR_NOT_INITIALIZED: ErrorCode = ErrorCode::new("ENGINE", "STATE", 11);
// Resource errors (021-030)
const ERR_FILE_NOTFOUND: ErrorCode = ErrorCode::new("io", "FILE", 21);
const BLOCKED_MUTEX: ErrorCode = ErrorCode::new("linker", "MUTEX", 24);
const COMPLETE_BUILD: ErrorCode = ErrorCode::new("build", "DONE", 999);
```
### Web API Service
```rust
// Input validation (001-010)
const ERR_MISSING_HEADER: ErrorCode = ErrorCode::new(Severity::Error, "HTTP", "HEADER", 1);
const ERR_INVALID_JSON: ErrorCode = ErrorCode::new(Severity::Error, "JSON", "PARSE", 3);
const ERR_DENIED: ErrorCode = ErrorCode::new(Severity::Error, "AUTH", "PERM", 8);
// State errors (011-020)
const ERR_SESSION_CLOSED: ErrorCode = ErrorCode::new(Severity::Error, "SESSION", "STATE", 13);
const ERR_TIMEOUT: ErrorCode = ErrorCode::new(Severity::Error, "REQUEST", "TIMEOUT", 17);
// Resource errors (021-030)
const ERR_USER_NOTFOUND: ErrorCode = ErrorCode::new(Severity::Error, "DB", "USER", 21);
const ERR_EMAIL_EXISTS: ErrorCode = ErrorCode::new(Severity::Error, "DB", "EMAIL", 22);
const ERR_DB_UNAVAILABLE: ErrorCode = ErrorCode::new(Severity::Error, "DB", "CONN", 27);
```
**Notice the pattern**: Across ALL projects:
- **001-010**: Input problems (missing param, invalid format, denied access)
- **011-020**: State problems (not initialized, closed, timeout)
- **021-030**: Resource problems (not found, already exists, unavailable)
**Users instantly understand error semantics just from the sequence number!**
---
## Enforcement
See `docs/ENFORCEMENT.md` for strategies to enforce these conventions.
**Summary**: These are **SHOULD** guidelines (RFC 2119), not strict requirements. Projects are encouraged but not forced to follow them.
---
## Evolution
This convention document may be updated in future versions to:
- Add new reserved sequences in empty slots (019-020, 030, 898-997)
- Refine semantic definitions based on real-world usage
- Document common patterns that emerge
**Stability Promise**: Existing reserved sequences (001-030, 998-999) will **never change meaning** in v0.x or v1.x. Only additions will be made to empty slots.
**Version 0.2.0 Changes** (this version):
- Reorganized into clear matrix pattern: Input/Data (0s), State/Lifecycle (10s), Resource/Storage (20s)
- Moved DUPLICATE from 014 → 007 (it's input validation, not state)
- Moved TIMEOUT from 007 → 017 (it's state/lifecycle, not input)
- Moved CONFLICT from 015 → 023 (it's resource conflict, not state)
- Added STALE (018) for outdated state detection
- Reordered resource errors for better logical flow
---
## References
- RFC 2119 (MUST/SHOULD/MAY): https://www.rfc-editor.org/rfc/rfc2119
- Semantic Versioning: https://semver.org/
- HTTP Status Codes (inspiration): https://developer.mozilla.org/en-US/docs/Web/HTTP/Status
---
**Made with 🦆 by the Waddling team**