Exception
Custom error handling with HTTP status codes, headers, and JavaScript-powered error responses.
The Exception node provides comprehensive error handling for workflows by allowing custom error responses with specific HTTP status codes, headers, and dynamically generated error content using JavaScript.
┌─────────────────────────────────────────────────────────┐
│ EXCEPTION HANDLING │
├─────────────────────────────────────────────────────────┤
│ │
│ ┌─────────┐ ┌─────────┐ │
│ │ API Call│────▶│ Process │ │
│ └────┬────┘ └─────────┘ │
│ │ │ │
│ │ │ (success) │
│ │ ▼ │
│ │ ┌─────────┐ │
│ │ │ SUCCESS │ │
│ │ │ PATH │ │
│ │ └─────────┘ │
│ │ │
│ │ (error/condition) │
│ ▼ │
│ ┌─────────┐ ┌─────────────────────────┐ │
│ │EXCEPTION│────▶│ Custom Error Response │ │
│ │ NODE │ │ • HTTP Status: 400 │ │
│ │ │ │ • Headers: Custom │ │
│ │ │ │ • Body: JavaScript │ │
│ │ │ │ • Terminates Workflow │ │
│ └─────────┘ └─────────────────────────┘ │
│ │
└─────────────────────────────────────────────────────────┘Configuration
| Property | Value |
|---|---|
| Workflow Types | Workflow |
Visual Appearance
Exception nodes are highlighted in red with an error circle icon in the workflow editor to clearly identify them as error handling components.
Output Configuration
Status Code Output
Configure the HTTP status code for the error response:
| Field | Type | Default | Description |
|---|---|---|---|
| Status | Integer | 500 | HTTP status code (100-599) |
Common HTTP Error Codes:
400 // Bad Request - Client error
401 // Unauthorized - Authentication required
403 // Forbidden - Access denied
404 // Not Found - Resource not found
422 // Unprocessable Entity - Validation failed
500 // Internal Server Error - Server error
502 // Bad Gateway - Upstream server error
503 // Service Unavailable - Server temporarily unavailableHeaders Output
Define custom HTTP headers for the error response:
| Field | Type | Default | Description |
|---|---|---|---|
| Headers | Object | {} | Key-value pairs for HTTP headers |
Example Headers Configuration:
{
"Content-Type": "application/json",
"X-Error-Code": "VALIDATION_FAILED",
"X-Request-ID": "{{ctx.vars.requestId}}",
"Cache-Control": "no-cache"
}Script Output (JavaScript)
Define the error response body using JavaScript with full code editor support:
| Field | Type | Default | Description |
|---|---|---|---|
| Body | JavaScript | return null; | JavaScript code that returns error response |
JavaScript Editor Features
The Exception node includes a JavaScript editor with auto-completion. For details on editor features, see the Code Editing & Schema Reference guide.
Key Features:
- Context Access: Auto-complete for
ctx.nodes,ctx.vars, andctx.user - Built-in Functions: Access to Axellero's JavaScript utilities
- Workflow Integration: Direct access to other node outputs
Script Access to Workflow Context:
// Access workflow data
return {
error: "Validation failed",
field: ctx.nodes.validator.outputs.failedField,
message: `Invalid value: ${ctx.nodes.input.outputs.value}`,
timestamp: new Date().toISOString(),
requestId: ctx.vars.requestId
};Exception Execution Flow
Workflow Termination
When an Exception node executes:
- Immediate Termination: Workflow execution stops immediately
- State Change: Workflow state changes to
FAILED - Response Formation: Custom status, headers, and body are prepared
- API Response: If workflow is exposed as API, returns the custom error response
Integration with Branch Nodes
Exception nodes are commonly connected to Branch node conditions:
// Branch condition that routes errors to Exception node
{{ctx.nodes.apiCall.error || ctx.nodes.validator.outputs.isValid === false}}Error Response Patterns
Validation Error Response
// Exception Script for validation errors
return {
error: "VALIDATION_FAILED",
details: {
field: ctx.nodes.validator.outputs.field,
value: ctx.nodes.validator.outputs.value,
constraint: "Must be between 1 and 100"
},
code: 422001
};Configuration:
- Status:
422 - Headers:
{"X-Error-Type": "validation"}
API Integration Error
// Exception Script for external API failures
const apiError = ctx.nodes.apiCall.error;
const statusCode = ctx.nodes.apiCall.metadata.statusCode;
return {
error: "EXTERNAL_SERVICE_ERROR",
service: "payment-gateway",
originalStatus: statusCode,
message: "Payment processing temporarily unavailable",
retryAfter: 300
};Configuration:
- Status:
502 - Headers:
{"Retry-After": "300", "X-Service": "payment-gateway"}
Authentication Error
// Exception Script for authentication failures
return {
error: "AUTHENTICATION_REQUIRED",
message: "Valid authentication token required",
loginUrl: ctx.consts.LOGIN_URL,
documentation: "https://docs.example.com/auth"
};Configuration:
- Status:
401 - Headers:
{"WWW-Authenticate": "Bearer realm=\"API\""}
Business Logic Error
// Exception Script for business rule violations
return {
error: "BUSINESS_RULE_VIOLATION",
rule: "insufficient_balance",
details: {
required: ctx.nodes.transaction.outputs.amount,
available: ctx.nodes.account.outputs.balance,
shortfall: ctx.nodes.transaction.outputs.amount - ctx.nodes.account.outputs.balance
}
};Configuration:
- Status:
400 - Headers:
{"X-Error-Category": "business-logic"}
Advanced JavaScript Features
Dynamic Status Codes
// Dynamic status based on error type
const error = ctx.nodes.processor.error;
if (error.includes("timeout")) {
// Status would need to be set via input configuration
return { error: "TIMEOUT", message: "Request timed out" };
} else if (error.includes("validation")) {
return { error: "INVALID_INPUT", details: ctx.nodes.validator.outputs };
} else {
return { error: "UNKNOWN_ERROR", trace: error };
}Contextual Error Information
// Rich error context with user and request details
return {
error: "OPERATION_FAILED",
context: {
user: {
id: ctx.user.id,
login: ctx.user.login,
roles: ctx.user.roles
},
workspace: ctx.workspace_slug,
app: ctx.app_slug,
execution: {
startedAt: ctx.nodes.start.metadata.executedAt,
failedAt: new Date().toISOString(),
node: "{{ctx.nodes.processor.code}}"
}
},
suggestion: "Please contact support with the execution ID"
};Error Aggregation
// Collect multiple validation errors
const errors = [];
if (ctx.nodes.emailValidator.error) {
errors.push({
field: "email",
message: "Invalid email format",
code: "EMAIL_INVALID"
});
}
if (ctx.nodes.passwordValidator.error) {
errors.push({
field: "password",
message: "Password too weak",
code: "PASSWORD_WEAK"
});
}
return {
error: "MULTIPLE_VALIDATION_ERRORS",
count: errors.length,
details: errors
};Best Practices
Error Message Design
- User-Friendly: Avoid exposing internal system details
- Actionable: Provide guidance on how to resolve the error
- Consistent: Use standardized error codes and formats
- Informative: Include relevant context without sensitive data
HTTP Status Code Selection
- 4xx for Client Errors: Invalid input, authentication, authorization
- 5xx for Server Errors: Internal failures, external service issues
- Specific Codes: Use appropriate codes (404 for not found, 422 for validation)
Header Configuration
- Content-Type: Always set appropriate content type
- Error Correlation: Include request IDs for tracking
- Cache Control: Prevent caching of error responses
- Security Headers: Remove sensitive information exposure
JavaScript Script Guidelines
- Error Handling: Use try-catch for complex operations
- Performance: Keep scripts lightweight for fast error responses
- Security: Validate and sanitize any user inputs included in errors
- Debugging: Include enough detail for troubleshooting without exposing internals
Integration Patterns
With API Endpoints
When workflows are exposed as HTTP endpoints, Exception nodes provide:
- Custom HTTP Status: Returned as actual HTTP response status
- Custom Headers: Merged with endpoint response headers
- Response Body: JavaScript return value becomes response body
With Branch Conditions
Common patterns for connecting Branch nodes to Exception nodes:
// Error condition routing
{{ctx.nodes.validation.error || !ctx.nodes.auth.outputs.isValid}}
// Business rule violations
{{ctx.nodes.account.outputs.balance < ctx.nodes.transaction.inputs.amount}}
// External service failures
{{ctx.nodes.apiCall.metadata.statusCode >= 500}}With Retry Logic
Exception nodes can be part of retry patterns:
// Count retry attempts and fail after limit
const retryCount = ctx.vars.retryCount || 0;
if (retryCount >= 3) {
return {
error: "MAX_RETRIES_EXCEEDED",
attempts: retryCount,
lastError: ctx.nodes.apiCall.error
};
}
// This would typically be in a non-exception node that increments retry countTroubleshooting
Common Issues
| Problem | Symptoms | Solution |
|---|---|---|
| Script Execution Error | Exception node fails to execute | Check JavaScript syntax and context access |
| Invalid Status Code | Workflow fails with status error | Ensure status code is between 100-599 |
| Headers Not Applied | Custom headers missing in response | Verify headers object format and JSON syntax |
| Workflow Doesn't Terminate | Execution continues after exception | Check that Exception node is properly connected |
Debugging Techniques
- Test Script Separately: Use node testing to verify JavaScript logic
- Check Status Code: Ensure valid HTTP status range
- Validate Headers: Verify JSON format for headers object
- Review Context Access: Confirm available workflow context data
- Examine Workflow Flow: Ensure proper connections to Exception node
Examples
API Gateway Error Handler
// Exception Node Configuration
Status: 502
Headers: {
"X-Error-Source": "api-gateway",
"Retry-After": "60"
}
// JavaScript Script:
const apiError = ctx.nodes.externalAPI.error;
const statusCode = ctx.nodes.externalAPI.metadata.statusCode;
return {
error: "EXTERNAL_SERVICE_UNAVAILABLE",
service: "payment-processor",
status: statusCode,
message: "Payment service is temporarily unavailable. Please try again later.",
retryAfter: 60,
supportContact: "support@example.com"
};Form Validation Error Handler
// Exception Node Configuration
Status: 422
Headers: {
"X-Error-Type": "validation",
"Content-Type": "application/json"
}
// JavaScript Script:
const validationErrors = ctx.nodes.formValidator.outputs.errors;
return {
error: "FORM_VALIDATION_FAILED",
message: "Please correct the following errors and try again",
fields: validationErrors.map(error => ({
field: error.field,
message: error.message,
code: error.code
})),
timestamp: new Date().toISOString()
};Rate Limit Error Handler
// Exception Node Configuration
Status: 429
Headers: {
"X-RateLimit-Reset": "{{ctx.vars.resetTime}}",
"Retry-After": "3600"
}
// JavaScript Script:
return {
error: "RATE_LIMIT_EXCEEDED",
message: "Too many requests. Please try again later.",
limit: ctx.consts.RATE_LIMIT,
remaining: 0,
resetTime: ctx.vars.resetTime,
retryAfter: 3600
};