@sfdxy/mule-lint 1.20.0 → 1.22.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (156) hide show
  1. package/README.md +63 -17
  2. package/dist/package.json +1 -1
  3. package/dist/src/core/XPathHelper.d.ts.map +1 -1
  4. package/dist/src/core/XPathHelper.js +8 -0
  5. package/dist/src/core/XPathHelper.js.map +1 -1
  6. package/dist/src/engine/LintEngine.d.ts +22 -0
  7. package/dist/src/engine/LintEngine.d.ts.map +1 -1
  8. package/dist/src/engine/LintEngine.js +105 -18
  9. package/dist/src/engine/LintEngine.js.map +1 -1
  10. package/dist/src/mcp/prompts/index.d.ts +1 -1
  11. package/dist/src/mcp/prompts/index.d.ts.map +1 -1
  12. package/dist/src/mcp/prompts/index.js +62 -1
  13. package/dist/src/mcp/prompts/index.js.map +1 -1
  14. package/dist/src/mcp/resources/index.js +114 -16
  15. package/dist/src/mcp/resources/index.js.map +1 -1
  16. package/dist/src/mcp/tools/getRuleDetails.d.ts.map +1 -1
  17. package/dist/src/mcp/tools/getRuleDetails.js +30 -1
  18. package/dist/src/mcp/tools/getRuleDetails.js.map +1 -1
  19. package/dist/src/rules/api-led/ApikitConsoleProductionRule.d.ts +22 -0
  20. package/dist/src/rules/api-led/ApikitConsoleProductionRule.d.ts.map +1 -0
  21. package/dist/src/rules/api-led/ApikitConsoleProductionRule.js +43 -0
  22. package/dist/src/rules/api-led/ApikitConsoleProductionRule.js.map +1 -0
  23. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.d.ts +24 -0
  24. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.d.ts.map +1 -0
  25. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.js +53 -0
  26. package/dist/src/rules/api-led/ApikitMainFlowStructureRule.js.map +1 -0
  27. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.d.ts +25 -0
  28. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.d.ts.map +1 -0
  29. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.js +59 -0
  30. package/dist/src/rules/api-led/ApikitStatusCodeVariableRule.js.map +1 -0
  31. package/dist/src/rules/connector/EventListenerNullGuardRule.d.ts +24 -0
  32. package/dist/src/rules/connector/EventListenerNullGuardRule.d.ts.map +1 -0
  33. package/dist/src/rules/connector/EventListenerNullGuardRule.js +58 -0
  34. package/dist/src/rules/connector/EventListenerNullGuardRule.js.map +1 -0
  35. package/dist/src/rules/connector/ReplayChannelConfigRule.d.ts +23 -0
  36. package/dist/src/rules/connector/ReplayChannelConfigRule.d.ts.map +1 -0
  37. package/dist/src/rules/connector/ReplayChannelConfigRule.js +52 -0
  38. package/dist/src/rules/connector/ReplayChannelConfigRule.js.map +1 -0
  39. package/dist/src/rules/dataweave/DataWeaveRules.d.ts +11 -4
  40. package/dist/src/rules/dataweave/DataWeaveRules.d.ts.map +1 -1
  41. package/dist/src/rules/dataweave/DataWeaveRules.js +20 -20
  42. package/dist/src/rules/dataweave/DataWeaveRules.js.map +1 -1
  43. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.d.ts +25 -0
  44. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.d.ts.map +1 -0
  45. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.js +63 -0
  46. package/dist/src/rules/dataweave/DuplicateTransformLogicRule.js.map +1 -0
  47. package/dist/src/rules/error-handling/CatchAllLastRule.d.ts +24 -0
  48. package/dist/src/rules/error-handling/CatchAllLastRule.d.ts.map +1 -0
  49. package/dist/src/rules/error-handling/CatchAllLastRule.js +65 -0
  50. package/dist/src/rules/error-handling/CatchAllLastRule.js.map +1 -0
  51. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.d.ts +28 -0
  52. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.d.ts.map +1 -0
  53. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.js +70 -0
  54. package/dist/src/rules/error-handling/ErrorHandlerTypeCoverageRule.js.map +1 -0
  55. package/dist/src/rules/error-handling/ErrorResponseStructureRule.d.ts +23 -0
  56. package/dist/src/rules/error-handling/ErrorResponseStructureRule.d.ts.map +1 -0
  57. package/dist/src/rules/error-handling/ErrorResponseStructureRule.js +73 -0
  58. package/dist/src/rules/error-handling/ErrorResponseStructureRule.js.map +1 -0
  59. package/dist/src/rules/error-handling/GenericErrorRule.d.ts +15 -3
  60. package/dist/src/rules/error-handling/GenericErrorRule.d.ts.map +1 -1
  61. package/dist/src/rules/error-handling/GenericErrorRule.js +58 -18
  62. package/dist/src/rules/error-handling/GenericErrorRule.js.map +1 -1
  63. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts +14 -15
  64. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.d.ts.map +1 -1
  65. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js +59 -38
  66. package/dist/src/rules/error-handling/GlobalErrorHandlerRule.js.map +1 -1
  67. package/dist/src/rules/error-handling/TryScopeRule.d.ts +5 -0
  68. package/dist/src/rules/error-handling/TryScopeRule.d.ts.map +1 -1
  69. package/dist/src/rules/error-handling/TryScopeRule.js +30 -7
  70. package/dist/src/rules/error-handling/TryScopeRule.js.map +1 -1
  71. package/dist/src/rules/http/ConnectionIdleTimeoutRule.d.ts +27 -0
  72. package/dist/src/rules/http/ConnectionIdleTimeoutRule.d.ts.map +1 -0
  73. package/dist/src/rules/http/ConnectionIdleTimeoutRule.js +46 -0
  74. package/dist/src/rules/http/ConnectionIdleTimeoutRule.js.map +1 -0
  75. package/dist/src/rules/index.d.ts +1 -1
  76. package/dist/src/rules/index.d.ts.map +1 -1
  77. package/dist/src/rules/index.js +50 -8
  78. package/dist/src/rules/index.js.map +1 -1
  79. package/dist/src/rules/logging/LoggerPayloadRule.d.ts +15 -0
  80. package/dist/src/rules/logging/LoggerPayloadRule.d.ts.map +1 -1
  81. package/dist/src/rules/logging/LoggerPayloadRule.js +48 -4
  82. package/dist/src/rules/logging/LoggerPayloadRule.js.map +1 -1
  83. package/dist/src/rules/operations/FlowRefTargetExistsRule.d.ts +23 -0
  84. package/dist/src/rules/operations/FlowRefTargetExistsRule.d.ts.map +1 -0
  85. package/dist/src/rules/operations/FlowRefTargetExistsRule.js +58 -0
  86. package/dist/src/rules/operations/FlowRefTargetExistsRule.js.map +1 -0
  87. package/dist/src/rules/operations/UnusedFlowRule.d.ts +20 -0
  88. package/dist/src/rules/operations/UnusedFlowRule.d.ts.map +1 -1
  89. package/dist/src/rules/operations/UnusedFlowRule.js +73 -7
  90. package/dist/src/rules/operations/UnusedFlowRule.js.map +1 -1
  91. package/dist/src/rules/operations/UnusedVariableRule.d.ts +31 -0
  92. package/dist/src/rules/operations/UnusedVariableRule.d.ts.map +1 -0
  93. package/dist/src/rules/operations/UnusedVariableRule.js +103 -0
  94. package/dist/src/rules/operations/UnusedVariableRule.js.map +1 -0
  95. package/dist/src/rules/performance/ListenerReconnectForeverRule.d.ts +28 -0
  96. package/dist/src/rules/performance/ListenerReconnectForeverRule.d.ts.map +1 -0
  97. package/dist/src/rules/performance/ListenerReconnectForeverRule.js +56 -0
  98. package/dist/src/rules/performance/ListenerReconnectForeverRule.js.map +1 -0
  99. package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts +7 -4
  100. package/dist/src/rules/performance/ReconnectionStrategyRule.d.ts.map +1 -1
  101. package/dist/src/rules/performance/ReconnectionStrategyRule.js +44 -24
  102. package/dist/src/rules/performance/ReconnectionStrategyRule.js.map +1 -1
  103. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.d.ts +36 -0
  104. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.d.ts.map +1 -0
  105. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.js +124 -0
  106. package/dist/src/rules/security/ConnectorCredentialsSecuredRule.js.map +1 -0
  107. package/dist/src/rules/security/HardcodedCredentialsRule.d.ts +4 -0
  108. package/dist/src/rules/security/HardcodedCredentialsRule.d.ts.map +1 -1
  109. package/dist/src/rules/security/HardcodedCredentialsRule.js +15 -0
  110. package/dist/src/rules/security/HardcodedCredentialsRule.js.map +1 -1
  111. package/dist/src/rules/security/SecurePropertiesEncryptionRule.d.ts +25 -0
  112. package/dist/src/rules/security/SecurePropertiesEncryptionRule.d.ts.map +1 -0
  113. package/dist/src/rules/security/SecurePropertiesEncryptionRule.js +59 -0
  114. package/dist/src/rules/security/SecurePropertiesEncryptionRule.js.map +1 -0
  115. package/dist/src/rules/security/SecurePropertiesKeyRule.d.ts +23 -0
  116. package/dist/src/rules/security/SecurePropertiesKeyRule.d.ts.map +1 -0
  117. package/dist/src/rules/security/SecurePropertiesKeyRule.js +45 -0
  118. package/dist/src/rules/security/SecurePropertiesKeyRule.js.map +1 -0
  119. package/dist/src/rules/security/TlsKeystorePasswordRule.d.ts +25 -0
  120. package/dist/src/rules/security/TlsKeystorePasswordRule.d.ts.map +1 -0
  121. package/dist/src/rules/security/TlsKeystorePasswordRule.js +63 -0
  122. package/dist/src/rules/security/TlsKeystorePasswordRule.js.map +1 -0
  123. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.d.ts +26 -0
  124. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.d.ts.map +1 -0
  125. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.js +61 -0
  126. package/dist/src/rules/standards/ApikitRouteVariableConsistencyRule.js.map +1 -0
  127. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.d.ts +34 -0
  128. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.d.ts.map +1 -0
  129. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.js +76 -0
  130. package/dist/src/rules/standards/ConfigPropertiesOrderingRule.js.map +1 -0
  131. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.d.ts +25 -0
  132. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.d.ts.map +1 -0
  133. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.js +111 -0
  134. package/dist/src/rules/standards/MissingEnvPropertiesDeclarationRule.js.map +1 -0
  135. package/dist/src/rules/yaml/YamlRules.d.ts +6 -2
  136. package/dist/src/rules/yaml/YamlRules.d.ts.map +1 -1
  137. package/dist/src/rules/yaml/YamlRules.js +15 -11
  138. package/dist/src/rules/yaml/YamlRules.js.map +1 -1
  139. package/dist/src/types/Rule.d.ts +13 -0
  140. package/dist/src/types/Rule.d.ts.map +1 -1
  141. package/docs/README.md +87 -27
  142. package/docs/best-practices/ci-cd.md +135 -0
  143. package/docs/best-practices/connector-patterns.md +253 -0
  144. package/docs/best-practices/dataweave-patterns.md +370 -0
  145. package/docs/best-practices/deployment-2026.md +171 -0
  146. package/docs/best-practices/error-handling.md +277 -0
  147. package/docs/best-practices/event-driven-patterns.md +424 -0
  148. package/docs/best-practices/logging.md +163 -0
  149. package/docs/best-practices/mulesoft-best-practices.md +72 -865
  150. package/docs/best-practices/performance.md +273 -0
  151. package/docs/best-practices/rules-catalog.md +337 -29
  152. package/docs/best-practices/security.md +181 -0
  153. package/docs/best-practices/testing.md +190 -0
  154. package/docs/best-practices/variable-contracts.md +191 -0
  155. package/docs/linter/architecture.md +119 -64
  156. package/package.json +1 -1
@@ -0,0 +1,171 @@
1
+ # Deployment & Modernization (2026)
2
+
3
+ > **Applies to:** All
4
+ > **Related Rules:** `OPS-001` · `PROJ-001` · `PROJ-002`
5
+ > **Last Updated:** April 2026
6
+
7
+ ## When to Read This
8
+
9
+ Read this when planning deployments, migrating to Java 17, adopting CloudHub 2.0, or modernizing tooling.
10
+
11
+ ---
12
+
13
+ ## Development Tooling (2026)
14
+
15
+ ### Anypoint Code Builder (ACB)
16
+
17
+ ACB (VS Code-based) is the recommended IDE for 2026+, replacing Anypoint Studio for new projects:
18
+
19
+ - **AI-assisted development** via MuleSoft Vibes
20
+ - **AsyncAPI 2.6 support** for event-driven API design
21
+ - **Native API Governance** validation during design
22
+ - **Integrated Exchange** publishing
23
+
24
+ ### MuleSoft CLI Tools
25
+
26
+ ```bash
27
+ # Lint analysis (CI/CD and local)
28
+ npx @sfdxy/mule-lint . -c .mulelintrc.json -f json
29
+
30
+ # Build + test
31
+ mvn clean test -Dmule.env=dev -Dsecure.key=test
32
+
33
+ # Package
34
+ mvn clean package -DskipTests
35
+ ```
36
+
37
+ ---
38
+
39
+ ## Java 17 Migration
40
+
41
+ Mule 4.9+ **mandates Java 17**. Migration checklist:
42
+
43
+ - [ ] Update `pom.xml` compiler settings and runtime version
44
+ - [ ] Run `jdeps` to identify dependencies on removed Java APIs
45
+ - [ ] Audit connector compatibility (most modern connectors are Java 17 compatible)
46
+ - [ ] Recompile custom connectors and Java modules
47
+ - [ ] Test DataWeave patterns — `DateTime` coercion is stricter in Java 17
48
+ - [ ] Update `log4j2.xml` for Java 17 module system changes
49
+ - [ ] Performance test in staging — JIT compiler and GC behavior differ
50
+
51
+ ---
52
+
53
+ ## Deployment Models
54
+
55
+ ### CloudHub 2.0 (Kubernetes-based)
56
+
57
+ | Feature | CloudHub 1.0 | CloudHub 2.0 |
58
+ | ------------------ | -------------------- | --------------------------------- |
59
+ | **Infrastructure** | VM-based workers | Kubernetes pods |
60
+ | **Scaling** | vCore-based | Pod replicas + HPA |
61
+ | **Networking** | Shared Load Balancer | Ingress / private networking |
62
+ | **Persistence** | Object Store V1 | Object Store V2 (pod-local) |
63
+ | **Monitoring** | Anypoint Monitoring | Anypoint Monitoring + K8s metrics |
64
+
65
+ ### Runtime Fabric (RTF)
66
+
67
+ For hybrid or private cloud deployments:
68
+
69
+ - Self-managed Kubernetes clusters
70
+ - Air-gapped environments
71
+ - Regulatory compliance (data residency)
72
+
73
+ ---
74
+
75
+ ## Environment Promotion
76
+
77
+ ```
78
+ Development → QA → Staging → Production
79
+ ↓ ↓ ↓ ↓
80
+ dev.yaml qa.yaml stg.yaml prod.yaml
81
+ ```
82
+
83
+ ### Deployment Checklist
84
+
85
+ | Item | Description |
86
+ | ------------------------ | ----------------------------- |
87
+ | ✅ All tests pass | MUnit and integration tests |
88
+ | ✅ Lint checks pass | No errors from mule-lint |
89
+ | ✅ Properties configured | Environment YAML verified |
90
+ | ✅ Secrets encrypted | No plaintext credentials |
91
+ | ✅ API Manager policies | Authentication, rate limiting |
92
+ | ✅ Monitoring configured | Dashboards and alerts ready |
93
+ | ✅ Java 17 verified | Runtime compatible |
94
+
95
+ ---
96
+
97
+ ## API Governance at Design Time
98
+
99
+ Before publishing to Exchange, validate API specifications against organizational rulesets:
100
+
101
+ 1. Define governance rulesets in API Governance
102
+ 2. Validate RAML/OAS/AsyncAPI specs during design in ACB
103
+ 3. Block publishing to Exchange if governance rules fail
104
+ 4. Automate governance checks in CI/CD pipeline
105
+
106
+ ---
107
+
108
+ ## API Versioning
109
+
110
+ ### URL-Based Versioning (Recommended)
111
+
112
+ ```
113
+ /api/v1/orders
114
+ /api/v2/orders
115
+ ```
116
+
117
+ ### Deprecation Strategy
118
+
119
+ 1. Announce deprecation timeline to consumers
120
+ 2. Return `Deprecation` and `Sunset` headers
121
+ 3. Monitor v1 vs v2 adoption
122
+ 4. Sunset after consumer migration
123
+
124
+ ```xml
125
+ <set-variable variableName="outboundHeaders" value="#[{
126
+ 'Deprecation': 'true',
127
+ 'Sunset': 'Sat, 01 Jan 2027 00:00:00 GMT',
128
+ 'Link': '</api/v2/orders>; rel=\"successor-version\"'
129
+ }]"/>
130
+ ```
131
+
132
+ ---
133
+
134
+ ## Monitoring & Observability
135
+
136
+ ### Three Pillars
137
+
138
+ | Pillar | Tool | Purpose |
139
+ | ----------- | ----------------------------------- | --------------------- |
140
+ | **Logs** | Anypoint Monitoring, Splunk, ELK | Debug, audit trail |
141
+ | **Metrics** | Anypoint Monitoring, Grafana | Performance, health |
142
+ | **Traces** | Anypoint Monitoring, Tracing module | Request flow, latency |
143
+
144
+ ### Key Metrics to Monitor
145
+
146
+ ```
147
+ Application Health:
148
+ ├── Response time (p50, p95, p99)
149
+ ├── Error rate (%)
150
+ ├── Throughput (requests/sec)
151
+ ├── Active connections
152
+ └── Worker CPU/Memory usage
153
+
154
+ Business Metrics:
155
+ ├── Records processed per hour
156
+ ├── Failed transactions
157
+ ├── API calls by consumer
158
+ └── Integration latency by backend
159
+ ```
160
+
161
+ ### Alerting
162
+
163
+ | Level | Condition | Response |
164
+ | ------------ | ------------------------------- | ----------------------- |
165
+ | **Critical** | Error rate > 10%, App down | Immediate on-call |
166
+ | **Warning** | Error rate > 5%, Latency > 5s | Investigate within 1h |
167
+ | **Info** | Resource > 70%, unusual pattern | Review in daily standup |
168
+
169
+ ---
170
+
171
+ **See also:** [CI/CD Integration](ci-cd.md) · [Security](security.md) · [Testing](testing.md)
@@ -0,0 +1,277 @@
1
+ # Error Handling Best Practices
2
+
3
+ > **Applies to:** HTTP APIs · Event-Driven · Batch · All
4
+ > **Related Rules:** `MULE-001` · `MULE-003` · `MULE-005` · `MULE-007` · `MULE-009` · `ERR-001` · `ERR-002` · `ERR-003` · `ERR-004`
5
+ > **Last Updated:** April 2026
6
+
7
+ ## When to Read This
8
+
9
+ Read this when designing, implementing, or reviewing error handling for any Mule 4 application — whether it exposes an HTTP API, listens to platform events, or processes batch data.
10
+
11
+ ---
12
+
13
+ ## Decision Matrix
14
+
15
+ | Project Type | Error Handler Location | Sets `httpStatus`? | Error Response Format | Correlation ID Source |
16
+ | ------------------------------ | ------------------------------------------------------------ | ------------------------------------------ | ---------------------------------------- | ------------------------------------------------------------- |
17
+ | **HTTP API (SAPI/Experience)** | Dedicated `error-handling.xml` or `global-error-handler.xml` | ✅ Yes — sets `httpStatus` in every branch | JSON error envelope → HTTP response | `attributes.headers.'x-correlation-id' default correlationId` |
18
+ | **Event-Driven (PAPI)** | Part of `error-handling.xml` | ❌ No — no HTTP response layer | Error payload → writeback + notification | Platform Event `EventUuid` |
19
+ | **Batch / Scheduler** | Inline or referenced `error-handler` | Depends on trigger | Logged error + retry/dead-letter | Generated UUID or scheduler ID |
20
+
21
+ ---
22
+
23
+ ## Key Principles
24
+
25
+ 1. **Every flow needs error handling** — either an explicit `<error-handler>` or a `ref` to a global one
26
+ 2. **Set HTTP status codes** — always set `httpStatus` variable for API responses (HTTP APIs only)
27
+ 3. **Include correlation ID** — enable distributed tracing across all API layers
28
+ 4. **Be specific about error types** — avoid catching `type="ANY"` except as the **last** handler in the chain
29
+ 5. **Consistent error envelope** — use the same response shape for all error types
30
+
31
+ ---
32
+
33
+ ## Patterns
34
+
35
+ ### Pattern 1: Global Error Handler (HTTP APIs)
36
+
37
+ **Use when:** building any HTTP-facing API (System API, Experience API, or APIKit-based Process API).
38
+
39
+ Every error branch should:
40
+
41
+ - Set `httpStatus` via `ee:set-variable`
42
+ - Build a JSON error response with `environment`, `correlationId`, `error`, and `message`
43
+ - Place `type="ANY"` as the **last** branch (catch-all)
44
+
45
+ ```xml
46
+ <!-- src/main/mule/common/error-handling.xml -->
47
+ <error-handler name="global-error-handler">
48
+
49
+ <!-- 400 Bad Request -->
50
+ <on-error-propagate type="APIKIT:BAD_REQUEST">
51
+ <ee:transform>
52
+ <ee:message>
53
+ <ee:set-payload><![CDATA[%dw 2.0
54
+ output application/json
55
+ ---
56
+ {
57
+ environment: p('mule.env'),
58
+ correlationId: (vars.correlationId default "") as String,
59
+ error: "InvalidInput",
60
+ message: error.detailedDescription default "Bad request"
61
+ }]]></ee:set-payload>
62
+ </ee:message>
63
+ <ee:variables>
64
+ <ee:set-variable variableName="httpStatus">400</ee:set-variable>
65
+ </ee:variables>
66
+ </ee:transform>
67
+ </on-error-propagate>
68
+
69
+ <!-- 404 Not Found -->
70
+ <on-error-propagate type="APIKIT:NOT_FOUND">
71
+ <!-- ... set httpStatus to 404, build response ... -->
72
+ </on-error-propagate>
73
+
74
+ <!-- 500 Internal Server Error (catch-all — MUST be last) -->
75
+ <on-error-propagate type="ANY" enableNotifications="true" logException="true">
76
+ <ee:transform>
77
+ <ee:message>
78
+ <ee:set-payload><![CDATA[%dw 2.0
79
+ output application/json
80
+ ---
81
+ {
82
+ environment: p('mule.env'),
83
+ correlationId: (vars.correlationId default "") as String,
84
+ error: "InternalError",
85
+ message: error.detailedDescription default "An unexpected error occurred."
86
+ }]]></ee:set-payload>
87
+ </ee:message>
88
+ <ee:variables>
89
+ <ee:set-variable variableName="httpStatus">500</ee:set-variable>
90
+ </ee:variables>
91
+ </ee:transform>
92
+ </on-error-propagate>
93
+
94
+ </error-handler>
95
+ ```
96
+
97
+ Reference it from the main API flow:
98
+
99
+ ```xml
100
+ <flow name="api-main">
101
+ <http:listener config-ref="httpListenerConfig" path="/api/*">
102
+ <http:response statusCode="#[vars.httpStatus default 200]"/>
103
+ <http:error-response statusCode="#[vars.httpStatus default 500]">
104
+ <http:body><![CDATA[#[payload]]]></http:body>
105
+ </http:error-response>
106
+ </http:listener>
107
+ <apikit:router config-ref="api-config"/>
108
+ <error-handler ref="global-error-handler"/>
109
+ </flow>
110
+ ```
111
+
112
+ ### Pattern 2: Error Handler (Event-Driven)
113
+
114
+ **Use when:** building a process API driven by Salesforce Platform Events, Anypoint MQ, or Kafka.
115
+
116
+ No `httpStatus`. Instead, errors trigger:
117
+
118
+ 1. Structured error payload build
119
+ 2. Writeback to source system (e.g., SF error field update)
120
+ 3. Notification dispatch (email, Slack, NetSuite error log)
121
+
122
+ ```xml
123
+ <error-handler name="global-error-handler">
124
+ <on-error-propagate enableNotifications="true" logException="true">
125
+ <!-- Build structured error payload -->
126
+ <ee:transform>
127
+ <ee:variables>
128
+ <ee:set-variable variableName="errorPayload"
129
+ resource="dwl/transforms/error-payload.dwl"/>
130
+ </ee:variables>
131
+ </ee:transform>
132
+ <!-- Log the error -->
133
+ <logger level="ERROR" message="#[vars.errorPayload]"
134
+ category="#[vars.logCategory default 'com.myorg.papi']"/>
135
+ <!-- Writeback error status to source system -->
136
+ <flow-ref name="sf-writeback-subflow"/>
137
+ <!-- Dispatch notifications -->
138
+ <flow-ref name="notification-router-subflow"/>
139
+ </on-error-propagate>
140
+ </error-handler>
141
+ ```
142
+
143
+ ### Pattern 3: Try Scope for Risky Operations
144
+
145
+ **Use when:** a flow makes 2+ external calls (HTTP requests, DB operations, connector calls).
146
+
147
+ ```xml
148
+ <!-- ❌ Bad — multiple calls without isolation -->
149
+ <flow name="process-order-flow">
150
+ <http:request config-ref="API"/>
151
+ <db:insert config-ref="Database"/>
152
+ </flow>
153
+
154
+ <!-- ✅ Good — each risky operation isolated -->
155
+ <flow name="process-order-flow">
156
+ <try>
157
+ <http:request config-ref="API"/>
158
+ <error-handler>
159
+ <on-error-propagate type="HTTP:CONNECTIVITY">
160
+ <logger category="com.myorg" level="ERROR"
161
+ message="#['API call failed: ' ++ error.description]"/>
162
+ </on-error-propagate>
163
+ </error-handler>
164
+ </try>
165
+ <try>
166
+ <db:insert config-ref="Database"/>
167
+ <error-handler>...</error-handler>
168
+ </try>
169
+ </flow>
170
+ ```
171
+
172
+ ### Pattern 4: Centralized Error Log Object (CRM Writeback)
173
+
174
+ **Use when:** integration errors need visibility in the CRM for operations teams (multi-system integrations where business users manage error resolution).
175
+
176
+ **Do NOT use when:** it's an internal-only SAPI where standard logging dashboards suffice, or for transient errors that will auto-recover via retry.
177
+
178
+ | Scenario | CRM Error Log? | Why |
179
+ | ---------------------------------------- | -------------- | ----------------------------------------------- |
180
+ | Multi-system sync (CRM ↔ ERP ↔ Payments) | ✅ | Ops needs single-pane visibility |
181
+ | Internal SAPI with no business users | ❌ | Logging + dashboards sufficient |
182
+ | Transient error (retry will succeed) | ❌ | Handle with retry, not logging |
183
+ | Real-time latency-sensitive flow | ⚠️ | Extra HTTP call per error; make async if needed |
184
+
185
+ **Standardized error payload contract:**
186
+
187
+ ```xml
188
+ <!-- Every caller builds this shape before calling errorLogFlow -->
189
+ <ee:transform doc:name="Error Payload">
190
+ <ee:set-payload><![CDATA[%dw 2.0
191
+ output application/json
192
+ ---
193
+ {
194
+ "Subject": "Failed to sync Invoice to ERP",
195
+ "Error": error.detailedDescription default "",
196
+ "Link": p('links.crm.record') ++ vars.recordId ++ "/view",
197
+ "RecordId": vars.recordId default ""
198
+ }]]></ee:set-payload>
199
+ </ee:transform>
200
+ <flow-ref name="errorLogFlow"/>
201
+ ```
202
+
203
+ **The error log flow — with self-healing handler:**
204
+
205
+ ```xml
206
+ <flow name="errorLogFlow">
207
+ <ee:transform doc:name="Map to CRM Error Object">
208
+ <ee:set-payload><![CDATA[%dw 2.0
209
+ output application/json
210
+ ---
211
+ {
212
+ "Application__c": "Mulesoft",
213
+ "Type__c": "Integration",
214
+ "Stacktrace__c": payload.Error default "",
215
+ "Record_Link__c": payload.Link default "",
216
+ "Record_Id__c": payload.RecordId default "",
217
+ "Subject__c": payload.Subject default ""
218
+ }]]></ee:set-payload>
219
+ </ee:transform>
220
+
221
+ <http:request method="POST" config-ref="SAPI_Config" path="/Error_Log__c"/>
222
+
223
+ <error-handler>
224
+ <!-- CRITICAL: Must NEVER throw — prevents infinite loop -->
225
+ <on-error-continue enableNotifications="true" logException="false">
226
+ <logger level="WARN"
227
+ message="Error logging failed: #[error.detailedDescription]"/>
228
+ </on-error-continue>
229
+ </error-handler>
230
+ </flow>
231
+ ```
232
+
233
+ > ⚠️ **Self-healing rule:** The `errorLogFlow` **must never propagate an error**. If it does, the parent flow's error handler re-enters the error log → infinite loop. Always use `on-error-continue`.
234
+
235
+ ---
236
+
237
+ ## Connector-Specific Error Types
238
+
239
+ ### Salesforce Connector (11.3.0+)
240
+
241
+ | Error Type | HTTP Status | Description |
242
+ | ------------------------------------- | ----------- | ---------------------------- |
243
+ | `SALESFORCE:CONNECTIVITY` | 502 | Connection failure to SF org |
244
+ | `SALESFORCE:INVALID_INPUT` | 400 | DML/SOQL validation error |
245
+ | `SALESFORCE:INVALID_RESPONSE` | 400 | Unparseable SF response |
246
+ | `SALESFORCE:FAULTY_RESPONSE` | 400 | SF returned error body |
247
+ | `SALESFORCE:NOT_FOUND` | 404 | Record not found |
248
+ | `SALESFORCE:TIMEOUT` | 504 | Connector timed out |
249
+ | `SALESFORCE:LIMIT_EXCEEDED` | 429 | API governor limit hit |
250
+ | `SALESFORCE:INSUFFICIENT_PERMISSIONS` | 403 | Permission denied |
251
+
252
+ ### APIKit Error Types
253
+
254
+ | Error Type | HTTP Status | Description |
255
+ | ------------------------------- | ----------- | --------------------------- |
256
+ | `APIKIT:BAD_REQUEST` | 400 | Schema validation failure |
257
+ | `APIKIT:NOT_FOUND` | 404 | Unknown URI path |
258
+ | `APIKIT:METHOD_NOT_ALLOWED` | 405 | HTTP verb not in RAML |
259
+ | `APIKIT:NOT_ACCEPTABLE` | 406 | Content negotiation failure |
260
+ | `APIKIT:UNSUPPORTED_MEDIA_TYPE` | 415 | Wrong Content-Type |
261
+
262
+ ---
263
+
264
+ ## Checklist
265
+
266
+ - [ ] Global error handler defined in a dedicated XML file
267
+ - [ ] Every flow has `<error-handler ref="global-error-handler"/>` or explicit handler
268
+ - [ ] `httpStatus` set in every error branch (HTTP APIs only)
269
+ - [ ] `correlationId` included in every error response
270
+ - [ ] `type="ANY"` is the **last** handler in the chain
271
+ - [ ] Connector-specific error types handled before generic ones
272
+ - [ ] Error response shape is consistent across all branches
273
+ - [ ] Error log flow uses `on-error-continue` — never cascades (Pattern 4)
274
+
275
+ ---
276
+
277
+ **See also:** [Variable Contracts](variable-contracts.md) · [Logging](logging.md) · [Rules Catalog](rules-catalog.md)