|
| 1 | +# Error Handling Examples |
| 2 | + |
| 3 | +This directory contains examples demonstrating structured error handling in rclnodejs. These examples showcase the comprehensive error class hierarchy for better debugging and error recovery patterns. |
| 4 | + |
| 5 | +## Overview |
| 6 | + |
| 7 | +rclnodejs provides 21 specialized error classes organized in a clear hierarchy, making it easier to catch, handle, and debug errors with rich context. All errors extend from `RclNodeError` and include properties like `code`, `nodeName`, `entityType`, `entityName`, and detailed context information. |
| 8 | + |
| 9 | +## Error Hierarchy |
| 10 | + |
| 11 | +``` |
| 12 | +RclNodeError (base) |
| 13 | +├── ValidationError |
| 14 | +│ ├── TypeValidationError |
| 15 | +│ ├── RangeValidationError |
| 16 | +│ └── NameValidationError |
| 17 | +├── OperationError |
| 18 | +│ ├── TimeoutError |
| 19 | +│ ├── AbortError |
| 20 | +│ ├── ServiceNotFoundError |
| 21 | +│ └── NodeNotFoundError |
| 22 | +├── ParameterError |
| 23 | +│ ├── ParameterNotFoundError |
| 24 | +│ ├── ParameterTypeError |
| 25 | +│ └── ReadOnlyParameterError |
| 26 | +├── TopicError |
| 27 | +│ ├── PublisherError |
| 28 | +│ └── SubscriptionError |
| 29 | +├── ActionError |
| 30 | +│ ├── GoalRejectedError |
| 31 | +│ └── ActionServerNotFoundError |
| 32 | +└── NativeError |
| 33 | +``` |
| 34 | + |
| 35 | +## Examples |
| 36 | + |
| 37 | +### 1. Type Validation (`error-handling-example.js` - Example 1) |
| 38 | + |
| 39 | +**Purpose**: Demonstrates catching `TypeValidationError` when providing wrong argument types. |
| 40 | + |
| 41 | +- **Functionality**: Attempts to create node with invalid type, catches and displays error details |
| 42 | +- **Features**: Shows `argumentName`, `expectedType`, and `providedValue` properties |
| 43 | +- **Key Properties**: `error.argumentName`, `error.expectedType`, `error.providedValue` |
| 44 | + |
| 45 | +### 2. Range Validation (`error-handling-example.js` - Example 2) |
| 46 | + |
| 47 | +**Purpose**: Demonstrates catching `RangeValidationError` for out-of-bounds values. |
| 48 | + |
| 49 | +- **Functionality**: Attempts to create rate with invalid frequency (>1000 Hz), catches error |
| 50 | +- **Features**: Shows `validationRule` and `providedValue` for constraint violations |
| 51 | +- **Key Properties**: `error.validationRule`, `error.providedValue`, `error.nodeName` |
| 52 | + |
| 53 | +### 3. Service Errors (`error-handling-example.js` - Example 3) |
| 54 | + |
| 55 | +**Purpose**: Demonstrates `TimeoutError` and `AbortError` handling for service operations. |
| 56 | + |
| 57 | +- **Functionality**: Shows timeout handling and manual request cancellation |
| 58 | +- **Features**: Demonstrates timeout with `sendRequestAsync({ timeout })` and `AbortController` |
| 59 | +- **Key Properties**: `error.timeout`, `error.operationType`, `error.entityName` |
| 60 | + |
| 61 | +### 4. Publisher Errors (`error-handling-example.js` - Example 4) |
| 62 | + |
| 63 | +**Purpose**: Demonstrates catching `PublisherError` during publisher creation. |
| 64 | + |
| 65 | +- **Functionality**: Attempts to create publisher with invalid message type |
| 66 | +- **Features**: Shows error handling for topic creation failures |
| 67 | +- **Key Class**: `PublisherError` |
| 68 | + |
| 69 | +### 5. Subscription Errors (`error-handling-example.js` - Example 5) |
| 70 | + |
| 71 | +**Purpose**: Demonstrates catching `SubscriptionError` during subscription creation. |
| 72 | + |
| 73 | +- **Functionality**: Attempts to create subscription with invalid message type |
| 74 | +- **Features**: Shows error handling for subscription creation failures |
| 75 | +- **Key Class**: `SubscriptionError` |
| 76 | + |
| 77 | +### 6. Parameter Errors (`error-handling-example.js` - Example 6) |
| 78 | + |
| 79 | +**Purpose**: Demonstrates `ParameterTypeError` for parameter type mismatches. |
| 80 | + |
| 81 | +- **Functionality**: Creates parameter with wrong value type, catches type error |
| 82 | +- **Features**: Shows parameter validation and type checking |
| 83 | +- **Key Class**: `ParameterTypeError` |
| 84 | + |
| 85 | +### 7. Name Validation (`error-handling-example.js` - Example 7) |
| 86 | + |
| 87 | +**Purpose**: Demonstrates `NameValidationError` for invalid ROS names. |
| 88 | + |
| 89 | +- **Functionality**: Validates topic name with invalid characters |
| 90 | +- **Features**: Shows `invalidIndex` property pointing to error location |
| 91 | +- **Key Properties**: `error.invalidIndex`, `error.message` |
| 92 | + |
| 93 | +### 8. Error Recovery (`error-handling-example.js` - Example 8) |
| 94 | + |
| 95 | +**Purpose**: Demonstrates retry logic with structured error handling. |
| 96 | + |
| 97 | +- **Functionality**: Implements retry pattern with different handling for timeout vs abort |
| 98 | +- **Features**: Shows differentiation between recoverable and non-recoverable errors |
| 99 | +- **Pattern**: Retry on `TimeoutError`, abort on `AbortError` or other errors |
| 100 | + |
| 101 | +### 9. Error Serialization (`error-handling-example.js` - Example 9) |
| 102 | + |
| 103 | +**Purpose**: Demonstrates using `toJSON()` for logging and debugging. |
| 104 | + |
| 105 | +- **Functionality**: Serializes error to JSON for structured logging |
| 106 | +- **Features**: Shows `toJSON()` method producing complete error information |
| 107 | +- **Method**: `error.toJSON()` |
| 108 | + |
| 109 | +### 10. Generic Error Handler (`error-handling-example.js` - Example 10) |
| 110 | + |
| 111 | +**Purpose**: Demonstrates reusable error handler for all rclnodejs errors. |
| 112 | + |
| 113 | +- **Functionality**: Implements `handleRclError()` function for consistent error handling |
| 114 | +- **Features**: Extracts common error properties, handles specific error types |
| 115 | +- **Pattern**: Single function handling all `RclNodeError` subclasses |
| 116 | + |
| 117 | +## How to Run |
| 118 | + |
| 119 | +1. **Prerequisites**: Ensure ROS 2 is installed and sourced |
| 120 | + |
| 121 | +2. **Run All Examples**: |
| 122 | + |
| 123 | + ```bash |
| 124 | + node example/error-handling/error-handling-example.js |
| 125 | + ``` |
| 126 | + |
| 127 | +3. **Expected Output**: Demonstrates all 10 error handling patterns with clear success indicators |
| 128 | + |
| 129 | +## Key Concepts Demonstrated |
| 130 | + |
| 131 | +### Error Properties |
| 132 | + |
| 133 | +All `RclNodeError` instances include: |
| 134 | + |
| 135 | +- `name`: Error class name (e.g., `'TypeValidationError'`) |
| 136 | +- `message`: Human-readable error description |
| 137 | +- `code`: Machine-readable error code (e.g., `'INVALID_TYPE'`) |
| 138 | +- `nodeName`: Associated node name (when applicable) |
| 139 | +- `entityType`: Entity type causing error (e.g., `'service'`, `'publisher'`) |
| 140 | +- `entityName`: Specific entity name (e.g., topic/service name) |
| 141 | +- `timestamp`: Error creation timestamp |
| 142 | + |
| 143 | +### Type-Specific Properties |
| 144 | + |
| 145 | +- **TypeValidationError**: `argumentName`, `expectedType`, `providedValue` |
| 146 | +- **RangeValidationError**: `validationRule`, `providedValue` |
| 147 | +- **NameValidationError**: `invalidIndex` |
| 148 | +- **TimeoutError**: `timeout`, `operationType` |
| 149 | +- **ParameterTypeError**: `argumentName`, `expectedType` |
| 150 | + |
| 151 | +### Error Methods |
| 152 | + |
| 153 | +- `toJSON()`: Serialize error to plain object for logging |
| 154 | +- `toString()`: Format error as readable string with context |
| 155 | + |
| 156 | +### Error Handling Patterns |
| 157 | + |
| 158 | +- **Type Guards**: Use `instanceof` to check specific error types |
| 159 | +- **Recovery Logic**: Different handling for recoverable vs non-recoverable errors |
| 160 | +- **Error Chaining**: Support for `cause` property linking related errors |
| 161 | +- **Structured Logging**: Use `toJSON()` for logging systems |
| 162 | +- **Generic Handlers**: Single function handling multiple error types |
| 163 | + |
| 164 | +## Usage Examples |
| 165 | + |
| 166 | +### Basic Error Catching |
| 167 | + |
| 168 | +```javascript |
| 169 | +try { |
| 170 | + rclnodejs.createNode(123, 'namespace'); |
| 171 | +} catch (error) { |
| 172 | + if (error instanceof rclnodejs.TypeValidationError) { |
| 173 | + console.log( |
| 174 | + `Expected ${error.expectedType}, got ${typeof error.providedValue}` |
| 175 | + ); |
| 176 | + } |
| 177 | +} |
| 178 | +``` |
| 179 | + |
| 180 | +### Service Timeout Handling |
| 181 | + |
| 182 | +```javascript |
| 183 | +try { |
| 184 | + await client.sendRequestAsync(request, { timeout: 5000 }); |
| 185 | +} catch (error) { |
| 186 | + if (error instanceof rclnodejs.TimeoutError) { |
| 187 | + console.log(`Timeout after ${error.timeout}ms`); |
| 188 | + } else if (error instanceof rclnodejs.AbortError) { |
| 189 | + console.log('Request cancelled'); |
| 190 | + } |
| 191 | +} |
| 192 | +``` |
| 193 | + |
| 194 | +### Generic Error Handler |
| 195 | + |
| 196 | +```javascript |
| 197 | +function handleRclError(error, operation) { |
| 198 | + if (!(error instanceof rclnodejs.RclNodeError)) { |
| 199 | + console.error(`Unexpected error: ${error.message}`); |
| 200 | + return; |
| 201 | + } |
| 202 | + |
| 203 | + const context = []; |
| 204 | + if (error.nodeName) context.push(`node: ${error.nodeName}`); |
| 205 | + if (error.entityName) |
| 206 | + context.push(`${error.entityType}: ${error.entityName}`); |
| 207 | + |
| 208 | + console.error(`${error.name} in ${operation}: ${error.message}`); |
| 209 | +} |
| 210 | +``` |
| 211 | + |
| 212 | +## Notes |
| 213 | + |
| 214 | +- All error classes extend `RclNodeError` for consistent `instanceof` checks |
| 215 | +- Error context properties are populated based on the operation |
| 216 | +- TypeScript definitions provide full type safety for error handling |
| 217 | +- Use `toJSON()` for integration with logging frameworks |
| 218 | +- Error codes are machine-readable constants for programmatic handling |
| 219 | +- Backward compatibility maintained - existing error handling continues to work |
0 commit comments