title: “Error Taxonomy & Structured Error Handling” version: 1.1.1 date: 2026-01-23
Error Taxonomy & Structured Error Handling
Comprehensive error taxonomy, codes, user messages, and structured error handling for BranchPy CLI, engines, dashboard, and server components.
Version: 1.1.1
Last Updated: January 23, 2026
Table of Contents
- Overview
- Error Code Format
- Error Taxonomy
- CLI Error Codes
- Server Error Codes
- Exception Hierarchy
- Error Messages
- Structured Error Class
- Error Handling Patterns
- Exit Codes
- Best Practices
- Cross-References
Overview
BranchPy uses a structured error system to handle, report, and communicate issues across its CLI, engines, dashboard, and server components. Errors are defined with stable codes, user-friendly messages, and support for context and diagnostics, ensuring robust and user-friendly error management.
Key Features
- Stable, extend-only error codes for common failure scenarios
- User-friendly error messages for CLI, dashboard, and logs
- Structured error class with context and diagnostics support
- Support for detailed error reporting and troubleshooting
- Cross-platform compatibility with Python 3 and TypeScript
- Consistent error format across CLI, server, and VS Code extension
Error Code Format
CLI Error Codes (E_-prefixed)
Pattern: E_<CATEGORY>_<SPECIFIC>
- E_: Error prefix
- CATEGORY: Component or subsystem (e.g.,
LIC,NET,PARSE,AUTH) - SPECIFIC: Descriptive identifier (e.g.,
INVALID,FAIL,MISSING)
Examples:
E_LIC_INVALID- License validation failedE_NET_FAIL- Network error while contacting remote serviceE_PARSE_SYNTAX- Syntax error during file parsing
Server Error Codes (BPY-prefixed)
Pattern: BPY-XXXX
- BPY: BranchPy namespace
- XXXX: 4-digit code (category range + specific error)
Example Categories:
1000–1099- Validation Errors1100–1199- Resource Not Found1200–1299- PILOT Module Errors1300–1399- Schema Errors2000–2999- Internal Server Errors
Examples:
BPY-1001- Missing required parameterBPY-1201- Path not found in stats2BPY-2001- Database connection failed
Error Taxonomy
CLI Error Categories
| Category | Code Prefix | Description | Examples |
|---|---|---|---|
| Licensing | E_LIC_* |
License validation, grace period, offline mode | E_LIC_INVALID, E_LIC_OFFLINE |
| Binary Management | E_BIN_* |
Runtime binaries, missing executables, signatures | E_BIN_MISSING, E_SIG_FAIL |
| Network | E_NET_* |
Connection failures, timeouts, API errors | E_NET_FAIL, E_NET_TIMEOUT |
| Permissions | E_PERM_* |
File system permissions, access denied | E_PERM_DENIED |
| Updates | E_UPDATE_* |
Update process, rollback, version conflicts | E_UPDATE_BUSY, E_UPDATE_ROLLBACK |
| Configuration | E_CFG_* |
Config file parsing, validation, corruption | E_CFG_CORRUPT, E_CFG_INVALID |
| Parsing | E_PARSE_* |
Syntax errors, malformed AST, invalid Python | E_PARSE_SYNTAX, E_PARSE_AST |
| Validation | E_VALID_* |
Schema validation, data validation | E_VALID_SCHEMA, E_VALID_DATA |
| Authentication | E_AUTH_* |
Credentials, tokens, session management | E_AUTH_INVALID, E_AUTH_EXPIRED |
| Authorization | E_AUTHZ_* |
Feature entitlement, plan limits, device limits | E_AUTHZ_FEATURE, E_AUTHZ_LIMIT |
| File System | E_FS_* |
File not found, disk full, I/O errors | E_FS_NOT_FOUND, E_FS_DISK_FULL |
| Analysis | E_ANALYSIS_* |
Cross-file tracking, CFG build, propagation | E_ANALYSIS_CFG, E_ANALYSIS_TRACK |
| AI | E_AI_* |
Provider errors, model availability, safety violations | E_AI_PROVIDER, E_AI_SAFETY |
| QuickFix | E_QUICKFIX_* |
Code transformation, unsafe operations | E_QUICKFIX_UNSAFE, E_QUICKFIX_TRANSFORM |
Server Error Categories
| Range | Category | Description | HTTP Status |
|---|---|---|---|
| 1000–1099 | Validation Errors | Invalid parameters, format errors, out of range | 400 |
| 1100–1199 | Resource Not Found | Project not found, report missing, config missing | 404 |
| 1200–1299 | PILOT Module Errors | Path not found, stats2 missing, invalid path format | 404, 400 |
| 1300–1399 | Schema Errors | JSON parse error, missing fields, version mismatch | 422 |
| 2000–2999 | Internal Server Errors | Database failures, file system errors, unexpected exceptions | 500 |
CLI Error Codes
Licensing Errors
| Code | Message | Description | User Action |
|---|---|---|---|
E_LIC_INVALID |
Your license couldn’t be validated. | License validation failed | Check license key, re-import .bpylic |
E_LIC_OFFLINE |
License server unreachable (grace period may apply). | Network unavailable, grace period active | Check network, verify grace period status |
Binary Management Errors
| Code | Message | Description | User Action |
|---|---|---|---|
E_BIN_MISSING |
Expected runtime binary not found. | Required executable missing | Run branchpy doctor, reinstall BranchPy |
E_SIG_FAIL |
Downloaded file failed integrity verification. | Signature verification failed | Re-download, check file integrity |
Network Errors
| Code | Message | Description | User Action |
|---|---|---|---|
E_NET_FAIL |
Network error while contacting a remote service. | Connection failure, timeout | Check network, verify server status |
Permission Errors
| Code | Message | Description | User Action |
|---|---|---|---|
E_PERM_DENIED |
Insufficient permissions to complete the operation. | Access denied, insufficient privileges | Check file permissions, run as administrator |
Update Errors
| Code | Message | Description | User Action |
|---|---|---|---|
E_UPDATE_BUSY |
Update is already in progress. | Concurrent update attempt | Wait for current update to complete |
E_UPDATE_ROLLBACK |
The new binary failed to start; rolled back to previous version. | Update failed, rollback triggered | Check logs, report issue if persistent |
Configuration Errors
| Code | Message | Description | User Action |
|---|---|---|---|
E_CFG_CORRUPT |
Configuration or state file is malformed. | Config file parsing failed | Check config syntax, restore from backup |
Server Error Codes
Validation Errors (1000–1099)
| Code | Message | HTTP Status | Client Action |
|---|---|---|---|
BPY-1001 |
Missing required parameter | 400 | Add parameter, retry |
BPY-1002 |
Invalid parameter format | 400 | Fix format, retry |
BPY-1003 |
Parameter out of range | 400 | Adjust value, retry |
Resource Not Found (1100–1199)
| Code | Message | HTTP Status | Client Action |
|---|---|---|---|
BPY-1101 |
Project not found | 404 | Verify project name |
BPY-1102 |
Report file not found | 404 | Generate report first |
BPY-1103 |
Configuration missing | 404 | Run init command |
PILOT Module Errors (1200–1299)
| Code | Message | HTTP Status | Client Action |
|---|---|---|---|
BPY-1201 |
Path not found in stats2 | 404 | Check available paths |
BPY-1202 |
stats2.json missing | 404 | Run branchpy stats2 |
BPY-1203 |
Invalid path format | 400 | Use correct path ID |
Schema Errors (1300–1399)
| Code | Message | HTTP Status | Client Action |
|---|---|---|---|
BPY-1301 |
JSON parse error | 422 | Regenerate report |
BPY-1302 |
Missing required field | 422 | Update schema version |
BPY-1303 |
Schema version mismatch | 422 | Upgrade client/server |
Internal Server Errors (2000–2999)
| Code | Message | HTTP Status | Client Action |
|---|---|---|---|
BPY-2001 |
Database connection failed | 500 | Retry with backoff |
BPY-2002 |
File system error | 500 | Check disk space |
BPY-2003 |
Unexpected exception | 500 | Report bug with logs |
Exception Hierarchy
All BranchPy exceptions inherit from BranchPyError:
BranchPyError (base exception)
├── ParseError
│ ├── SyntaxError
│ ├── InvalidPythonCodeError
│ └── MalformedASTError
├── ValidationError
│ ├── ConfigValidationError
│ ├── SchemaValidationError
│ └── DataValidationError
├── ConfigError
│ ├── ConfigNotFoundError
│ ├── InvalidConfigError
│ └── ConfigMigrationError
├── AuthenticationError
│ ├── InvalidCredentialsError
│ ├── TokenExpiredError
│ └── TokenInvalidError
├── AuthorizationError
│ ├── FeatureNotEntitledError
│ ├── PlanLimitExceededError
│ └── DeviceLimitExceededError
├── NetworkError
│ ├── ConnectionError
│ ├── TimeoutError
│ └── APIError
├── FileSystemError
│ ├── FileNotFoundError
│ ├── PermissionError
│ └── DiskFullError
├── AnalysisError
│ ├── CrossFileTrackingError
│ ├── PropagationError
│ └── CFGBuildError
├── AIError
│ ├── ProviderError
│ ├── ModelNotAvailableError
│ └── SafetyViolationError
└── QuickFixError
├── TransformationError
├── UnsafeOperationError
└── InvalidExpressionError
Error Messages
ERROR_MESSAGES Dictionary
User-friendly error messages mapped to error codes:
ERROR_MESSAGES = {
E_LIC_INVALID: "Your license couldn't be validated.",
E_LIC_OFFLINE: "License server unreachable (grace period may apply).",
E_BIN_MISSING: "Expected runtime binary not found.",
E_SIG_FAIL: "Downloaded file failed integrity verification.",
E_NET_FAIL: "Network error while contacting a remote service.",
E_PERM_DENIED: "Insufficient permissions to complete the operation.",
E_UPDATE_BUSY: "Update is already in progress.",
E_UPDATE_ROLLBACK: "The new binary failed to start; rolled back to previous version.",
E_CFG_CORRUPT: "Configuration or state file is malformed.",
}
Structured Error Class
BranchPyError
Base class for all BranchPy exceptions with structured fields for context and diagnostics.
@dataclass
class BranchPyError(Exception):
code: str # Error code (e.g., E_LIC_INVALID)
detail: Optional[str] = None # Additional detail message
context: Optional[dict] = None # Context dictionary (url, file_path, etc.)
def __str__(self) -> str:
base = ERROR_MESSAGES.get(self.code, self.code)
if self.detail:
base += f" Detail: {self.detail}"
return base
def to_user_block(self, version: str, platform: str, log_path: str) -> str:
"""Generate support-ready error report block."""
lines = [
ERROR_MESSAGES.get(self.code, self.code),
"",
"Copy this block if you need support:",
f"CODE: {self.code}",
f"VERSION: {version}",
f"PLATFORM: {platform}",
f"LOG: {log_path}",
]
if self.context:
for k, v in self.context.items():
lines.append(f"{k.upper()}: {v}")
return "\n".join(lines)
Usage Example
# Raising an error with context
raise BranchPyError(
E_NET_FAIL,
detail="Timeout contacting server",
context={"url": "https://api.branchpy.com"}
)
# Generating support block
try:
# ... operation ...
except BranchPyError as e:
print(e.to_user_block(
version="1.1.1",
platform="Windows",
log_path="C:\\Users\\user\\.branchpy\\logs\\error.log"
))
Server Error Payload (JSON)
{
"error": true,
"code": "BPY-1201",
"message": "Path p999 not found in project myGame",
"severity": "warn",
"suggestion": "Check available paths using /paths endpoint",
"correlation_id": "abc123",
"context": {
"project_name": "myGame",
"requested_path": "p999",
"available_paths": ["p001", "p002", "p003"]
}
}
Error Handling Patterns
Typical Workflow
- Raise BranchPyError with appropriate code, detail, and context
- Map error codes to user-friendly messages for display
- Use to_user_block for generating support-ready error reports
- Validate error handling logic with test scripts and example usage
CLI Error Handling
import sys
from branchpy.errors import BranchPyError, ParseError, AuthenticationError
try:
main()
sys.exit(0) # Success
except ParseError:
sys.exit(2)
except AuthenticationError:
sys.exit(5)
except BranchPyError as e:
logger.error(f"{e.code}: {e}")
sys.exit(1)
except Exception as e:
logger.exception("Unexpected error")
sys.exit(1)
Server Error Response
interface ErrorResponse {
error: true;
code: string; // e.g., "BPY-1201"
message: string; // Human-readable error
severity: 'info' | 'warn' | 'error';
suggestion?: string; // Optional fix guidance
correlation_id?: string; // Request tracking ID
}
Retry & Backoff (Server Errors)
async function fetchWithRetry(url: string, maxAttempts = 3): Promise<Response> {
for (let attempt = 1; attempt <= maxAttempts; attempt++) {
try {
const response = await fetch(url);
if (response.ok || response.status < 500) {
return response; // Success or client error (no retry)
}
// 5xx error → retry
} catch (error) {
// Network error → retry
}
if (attempt < maxAttempts) {
const delayMs = Math.min(1000 * Math.pow(2, attempt - 1), 8000);
await new Promise(resolve => setTimeout(resolve, delayMs));
}
}
throw new Error(`Failed after ${maxAttempts} attempts`);
}
Delays:
- Attempt 1 → immediate
- Attempt 2 → 1s delay
- Attempt 3 → 2s delay
- Maximum delay → 8s
Exit Codes
Exit codes for CLI commands and scripts:
# Exit codes
EXIT_SUCCESS = 0 # Success, no issues
EXIT_ERROR = 1 # General error
EXIT_PARSE_ERROR = 2 # Parsing failed
EXIT_VALIDATION_ERROR = 3 # Validation failed
EXIT_CONFIG_ERROR = 4 # Configuration error
EXIT_AUTH_ERROR = 5 # Authentication failed
EXIT_AUTHZ_ERROR = 6 # Authorization failed
EXIT_NET_ERROR = 7 # Network error
EXIT_FS_ERROR = 8 # File system error
EXIT_ANALYSIS_ERROR = 9 # Analysis error
EXIT_AI_ERROR = 10 # AI provider error
EXIT_QUICKFIX_ERROR = 11 # QuickFix transformation error
Exit Code Mapping
| Exit Code | Constant | Meaning | Example |
|---|---|---|---|
0 |
EXIT_SUCCESS |
Success, no issues | Analysis completed successfully |
1 |
EXIT_ERROR |
General error | Unexpected exception |
2 |
EXIT_PARSE_ERROR |
Parsing failed | Syntax error in .rpy file |
3 |
EXIT_VALIDATION_ERROR |
Validation failed | Schema validation error |
4 |
EXIT_CONFIG_ERROR |
Configuration error | Invalid .branchpy.toml |
5 |
EXIT_AUTH_ERROR |
Authentication failed | Invalid credentials |
6 |
EXIT_AUTHZ_ERROR |
Authorization failed | Feature not entitled |
7 |
EXIT_NET_ERROR |
Network error | Connection timeout |
8 |
EXIT_FS_ERROR |
File system error | Permission denied |
9 |
EXIT_ANALYSIS_ERROR |
Analysis error | CFG build failed |
10 |
EXIT_AI_ERROR |
AI provider error | Model not available |
11 |
EXIT_QUICKFIX_ERROR |
QuickFix transformation error | Unsafe operation |
Best Practices
1. Use Stable Error Codes
- Error codes are extend-only for backward compatibility
- Add new codes for emerging failure scenarios
- Never change existing error code meanings
2. Provide Detailed Context
# Good
raise BranchPyError(
E_NET_FAIL,
detail="Timeout contacting server after 30s",
context={
"url": "https://api.branchpy.com",
"timeout_seconds": 30,
"retry_count": 3
}
)
# Avoid
raise BranchPyError(E_NET_FAIL)
3. Use to_user_block for Support
try:
# ... operation ...
except BranchPyError as e:
support_block = e.to_user_block(
version=VERSION,
platform=platform.system(),
log_path=log_file_path
)
print(support_block)
4. Log Before Raising
logger.error(
"License validation failed",
extra={
"license_key": license_key[:8] + "...",
"validation_url": validation_url,
"error": error_msg
}
)
raise BranchPyError(E_LIC_INVALID, detail=error_msg)
5. Handle Errors Gracefully
# Provide helpful error messages
try:
require_feature("ai_review")
except FeatureNotEntitledError as e:
print(f"⚠️ AI Review requires Pro plan")
print(f"Your current plan: {e.details['current_plan']}")
print(f"Upgrade at: https://branchpy.com/upgrade")
6. Test Error Handling
import pytest
from branchpy.errors import BranchPyError, E_LIC_INVALID
def test_license_error_handling():
with pytest.raises(BranchPyError) as exc_info:
validate_license("invalid-key")
assert exc_info.value.code == E_LIC_INVALID
assert "context" in exc_info.value.__dict__
Performance Considerations
- Optimized for efficient error reporting and diagnostics
- Minimal overhead for exception creation and handling
- Structured context avoids string concatenation overhead
- Support-ready blocks generated on-demand
Error Handling & Edge Cases
- Handles missing codes: Falls back to error code string
- Handles malformed messages: Provides generic message
- Handles context errors: Validates context dictionary
- Provides detailed error messages and logging for debugging
Extending & Customization
Adding New Error Codes
-
Add error code constant to
branchpy/errors.py:E_NEW_ERROR = "E_NEW_ERROR" -
Add user-friendly message to
ERROR_MESSAGES:ERROR_MESSAGES = { # ... existing codes ... E_NEW_ERROR: "User-friendly message for new error.", } -
Document in error taxonomy (this file)
Extending BranchPyError Class
@dataclass
class EnhancedBranchPyError(BranchPyError):
"""Extended error class with additional diagnostics."""
timestamp: Optional[str] = None
stack_trace: Optional[str] = None
def to_detailed_report(self) -> str:
"""Generate detailed diagnostic report."""
report = self.to_user_block(VERSION, platform.system(), log_path)
if self.timestamp:
report += f"\nTIMESTAMP: {self.timestamp}"
if self.stack_trace:
report += f"\nSTACK TRACE:\n{self.stack_trace}"
return report
Integration
Error system works with:
- CLI - Command-line interface error handling
- Engines - Analysis engine error reporting
- Dashboard - Web dashboard error display
- Core modules - Central error management
- Server - REST API error responses
- VS Code Extension - Extension error mapping and display
Supported Environments
- Python 3.8+ for CLI and engines
- TypeScript/Node.js for server and VS Code extension
- Cross-platform (Windows, macOS, Linux)
Cross-References
Related Documentation
- API Error Codes & Handling - Exception hierarchy and API error handling
- API Contracts - Request/response formats and error handling
- API README - API overview
- Server Protocol - Server error codes and responses
- Server Architecture - Server error handling
- Backend Architecture - Backend error handling
- Logging - Error logging configuration
Source References:
- Original Error Documentation:
docs/v1.1.0/Errors/BranchPy_Errors_Documentation.md - API Error Documentation:
docs/v1.1.0/API/errors.md - Error Implementation:
BranchPyApp/branchpy/errors.py - Error Constants:
BranchPyApp/branchpy/contract.py - Server Protocol:
docs/v1.1.0/Server/PROTOCOL.md - Version: 1.1.1
- Last Updated: January 23, 2026