Files
rspade_system/app/RSpade/man/error_handling.txt
root f6fac6c4bc Fix bin/publish: copy docs.dist from project root
Fix bin/publish: use correct .env path for rspade_system
Fix bin/publish script: prevent grep exit code 1 from terminating script

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-10-21 02:08:33 +00:00

289 lines
10 KiB
Plaintext
Executable File

NAME
error_handling - RSX framework error handling patterns and shouldnt_happen()
SYNOPSIS
Error handling philosophy, fail-loud patterns, and sanity check functions
DESCRIPTION
The RSX framework enforces strict error handling that prioritizes early
detection and clear failure over silent continuation. This document covers
error handling patterns, the shouldnt_happen() function, and examples of
proper failure handling in security-critical and framework contexts.
CORE PHILOSOPHY
Fail Loud, Not Silent:
- Errors must be immediately apparent during development
- No silent fallbacks or alternative code paths
- Exception handlers should ONLY format error display, not provide alternatives
- One deterministic way to do things
No Defensive Coding for Core Classes:
- Core framework classes in /app/RSpade/Core/ are ALWAYS present
- Never check if core classes exist: if (typeof Rsx_Manifest !== 'undefined')
- Just use them directly: Rsx_Manifest.define()
- The build system guarantees core classes are present
SHOULDNT_HAPPEN() FUNCTION
Purpose:
Explicitly fail when encountering "impossible" conditions that indicate
broken assumptions or corrupted application state.
When to Use:
- After loading files, if expected classes don't exist
- When required files are missing after checking they should exist
- When database operations return unexpected null values
- When array keys that must exist are missing
- Any time you write a comment like "this shouldn't happen"
- When critical resources fail to initialize
- When configuration validation fails in unexpected ways
PHP Usage Examples:
// Class loading validation
if (!class_exists($expected_class)) {
shouldnt_happen("Class {$expected_class} should have been loaded in Phase 3");
}
// File system validation
if (!file_exists($required_file)) {
shouldnt_happen("Required config file missing: {$required_file}");
}
// Database state validation
$user = User::find($user_id);
if (!$user && $user_id > 0) {
shouldnt_happen("User ID {$user_id} should exist based on session data");
}
// Array key validation
if (!isset($config['required_setting'])) {
shouldnt_happen("Config missing required_setting after validation");
}
// Resource initialization
if (!$this->manifest_data) {
shouldnt_happen("Manifest data not loaded after successful build");
}
JavaScript Usage Examples:
// DOM element validation
if (!element) {
shouldnt_happen(`Required DOM element #${elementId} not found`);
}
// API response validation
if (!data.requiredField) {
shouldnt_happen('API response missing required field: requiredField');
}
// Framework state validation
if (!Rsx._initialized) {
shouldnt_happen('Rsx framework not initialized before use');
}
// Component validation
if (!this.template_rendered) {
shouldnt_happen('Component ready() called before template render');
}
SECURITY-CRITICAL ERROR HANDLING
Never Continue on Security Failures:
Security validation must fail loudly. Never provide fallback paths
that could compromise security.
String Sanitization Example:
// ❌ CATASTROPHIC - Silent security failure
try {
$clean = Sanitizer::sanitize($user_input);
} catch (Exception $e) {
$clean = $user_input; // DISASTER - unsanitized data continues
}
// ✅ CORRECT - Fail loudly on security failure
$clean = Sanitizer::sanitize($user_input); // Let it throw if it fails
Authentication Example:
// ❌ BAD - Silent fallback to unauthenticated
try {
$user = Auth::validateToken($token);
} catch (Exception $e) {
$user = null; // Dangerous - proceeds without authentication
}
// ✅ GOOD - Fail loudly on auth failure
$user = Auth::validateToken($token); // Let it throw if invalid
Authorization Example:
// ❌ BAD - Silent permission failure
if (!$user->hasPermission('admin')) {
// Log error but continue anyway
Log::error('Permission denied');
return $default_view; // WRONG - shows content without permission
}
// ✅ GOOD - Fail loudly on permission failure
if (!$user->hasPermission('admin')) {
throw new UnauthorizedException('Admin access required');
}
FRAMEWORK ERROR PATTERNS
No Alternative Code Paths:
The framework should have ONE deterministic way to do things.
No redundant fallback systems.
Examples of Anti-Patterns:
// ❌ BAD - Alternative fallback system
try {
$result = NewApiService::process($data);
} catch (Exception $e) {
$result = LegacyApiService::process($data); // WRONG
}
// ❌ BAD - Silent failure continuation
if (!$critical_resource) {
return; // WRONG - silent continue
}
// ❌ BAD - Defensive existence checks for core classes
if (class_exists('Rsx_Manifest')) {
Rsx_Manifest::register(); // WRONG - core classes always exist
}
Correct Patterns:
// ✅ GOOD - Single path, fail loudly
$result = NewApiService::process($data); // Let it throw
// ✅ GOOD - Explicit failure on missing resources
if (!$critical_resource) {
shouldnt_happen("Critical resource not initialized");
}
// ✅ GOOD - Direct usage of core classes
Rsx_Manifest::register(); // Core classes guaranteed present
EXCEPTION HANDLING GUIDELINES
Exception Handlers Should Only Format:
Exception handlers should format error display, not provide
alternative functionality.
Web Error Pages:
// ✅ GOOD - Format error for user display
try {
return $controller->handle($request);
} catch (Exception $e) {
return view('errors.500', ['error' => $e->getMessage()]);
}
API Error Responses:
// ✅ GOOD - Format error for API response
try {
$data = $service->processRequest($request);
} catch (ValidationException $e) {
return response()->json(['error' => $e->errors()], 422);
}
Development Error Display:
// ✅ GOOD - Enhanced error display for development
try {
return $result;
} catch (Exception $e) {
if (config('app.debug')) {
return $this->formatDevelopmentError($e);
}
throw $e; // Re-throw in production
}
DEBUGGING ERROR PATTERNS
Use rsx_dump_die() for Development:
Preferred debugging function that halts execution after output.
Use liberally during debugging, remove after fixing issues.
Examples:
rsx_dump_die($user); // Debug single value
rsx_dump_die($request, $params, $result); // Debug multiple values
Never Hide Debugging Information:
// ❌ BAD - Hidden debug information
try {
rsx_dump_die($debug_data);
} catch (Exception $e) {
// Silent ignore - WRONG
}
// ✅ GOOD - Let debug output show
rsx_dump_die($debug_data); // Always visible
VALIDATION ERROR HANDLING
Input Validation:
Input validation should throw exceptions immediately when validation
fails. Never continue with invalid data.
Model Validation:
// ✅ GOOD - Fail on validation error
$user = new User($data);
$user->validate(); // Throws if invalid
$user->save();
// ❌ BAD - Continue with invalid data
$user = new User($data);
if (!$user->validate()) {
$user->email = 'default@example.com'; // WRONG
}
$user->save();
Configuration Validation:
// ✅ GOOD - Fail on invalid config
if (!config('app.key')) {
shouldnt_happen('Application key not configured');
}
// ❌ BAD - Default fallback config
$key = config('app.key') ?: 'default-key'; // WRONG
TESTING ERROR SCENARIOS
Always Test the Failure Path:
Ensure errors are visible and properly formatted during development.
Error Testing Examples:
// Test that exceptions are thrown
$this->expectException(ValidationException::class);
$service->processInvalidData($bad_data);
// Test error message content
try {
$service->processData(null);
$this->fail('Expected exception not thrown');
} catch (Exception $e) {
$this->assertStringContains('Data cannot be null', $e->getMessage());
}
// Test shouldnt_happen() scenarios
try {
$service->processWithMissingDependency();
$this->fail('shouldnt_happen not triggered');
} catch (RuntimeException $e) {
$this->assertStringContains('shouldnt_happen', $e->getMessage());
}
COMMON ANTI-PATTERNS TO AVOID
Silent Continues:
Never continue execution when critical operations fail.
Redundant Systems:
Never implement fallback systems that do the same thing differently.
Defensive Core Checks:
Never check if core framework classes exist.
Security Fallbacks:
Never provide fallback authentication or authorization.
Default Values on Failure:
Never substitute default values when validation fails.
Try-Catch Workarounds:
Never use try-catch to work around expected failures.
SEE ALSO
coding_standards - General coding conventions and standards
console_debug - Debug output and filtering system
config_rsx - Framework configuration patterns