Our API had 14 endpoints and 14 different error response formats. The mobile team spent 3 days writing separate error parsers for each one. I standardized everything to RFC 7807 with one DataWeave transform.
TL;DR
- RFC 7807 defines a standard error format: type, title, status, detail, timestamp
- One DataWeave error mapping lookup replaces 14 inconsistent formats
- The
defaultclause on the lookup is critical — unmapped errors return null without it -
application/problem+jsonMIME type supported since Mule 4.4
The Problem: 14 Endpoints, 14 Error Formats
// Endpoint A
{"error": "not found"}
// Endpoint B
{"message": "Resource missing", "code": 404}
// Endpoint C
{"errors": [{"field": "email", "issue": "invalid"}]}
The mobile team needed a different error parser for each endpoint. 3 days of defensive parsing just to show error messages.
The Solution: RFC 7807 Error Envelope
%dw 2.0
output application/json
var errorMapping = {
"HTTP:BAD_REQUEST": { status: 400, title: "Bad Request", "type": "client-error" },
"HTTP:UNAUTHORIZED": { status: 401, title: "Unauthorized", "type": "authentication" },
"HTTP:NOT_FOUND": { status: 404, title: "Not Found", "type": "not-found" },
"HTTP:TIMEOUT": { status: 504, title: "Gateway Timeout", "type": "timeout" }
}
var errorInfo = errorMapping[payload.error.errorType.identifier] default { status: 500, title: "Internal Server Error", "type": "server-error" }
---
{
"type": "https://api.example.com/errors/$(errorInfo.'type')",
title: "errorInfo.title,"
status: errorInfo.status,
detail: payload.error.description,
timestamp: now()
}
Every error, every endpoint, same format. The mobile team wrote 1 parser.
100 production-ready DataWeave patterns with tests: mulesoft-cookbook on GitHub
The Error Mapping Lookup
The errorMapping object maps Mule error type identifiers to HTTP semantics:
var errorInfo = errorMapping[payload.error.errorType.identifier]
default { status: 500, title: "Internal Server Error", "type": "server-error" }
errorType.identifier comes from Mule's error object — values like "HTTP:BAD_REQUEST", "HTTP:NOT_FOUND", "VALIDATION:INVALID_PAYLOAD".
The lookup errorMapping["HTTP:NOT_FOUND"] returns the mapped status and title. If the error type isn't in the mapping, default provides a 500 fallback.
Trap: Missing default Clause
Without default:
var errorInfo = errorMapping[payload.error.errorType.identifier]
An unmapped error type (like "CUSTOM:BUSINESS_RULE") returns null. Your response:
{"type": null, "title": null, "status": null, "detail": "Business rule violated"}
Technically valid JSON. Completely useless to the client. The mobile app shows "null" as the error title.
I hit this in production when a custom connector threw "CUSTOM:RATE_EXCEEDED" — an error type I hadn't mapped. The API returned a null-filled error response. The mobile app crashed trying to display null.title.
Rule: Always use default on error mapping lookups. The default should be a valid 500 response, not null.
The Reserved Word Trap
errorInfo.'type' // Works — quoted field access
errorInfo.type // Parse error — "type" is reserved in DataWeave
type is a reserved keyword. When your error mapping uses type as a field name, you must access it with quotes: errorInfo.'type'. Without quotes, DataWeave throws a parse error.
I spent 20 minutes on this. The error message says "unexpected token" — it doesn't mention that type is reserved.
RFC 7807 Fields
| Field | Required | Purpose |
|---|---|---|
| type | Yes | URI identifying the error category |
| title | Yes | Human-readable error title |
| status | Yes | HTTP status code |
| detail | Yes | Specific error description |
| instance | No | URI of the failing request |
| timestamp | No | When the error occurred |
| correlationId | No | Request trace ID |
What I Do Now
- Every API project gets the error envelope pattern in the global error handler
-
defaulton every mapping lookup — no exceptions - Quoted access for
typefield - I add
correlationIdfrom the Mule correlation ID for trace support - Content-Type:
application/problem+json(supported since Mule 4.4)
100 patterns with MUnit tests: github.com/shakarbisetty/mulesoft-cookbook
60-second video walkthroughs: youtube.com/@SanThaParv
Top comments (0)