diff --git a/docs/api-reference/openapi.json b/docs/api-reference/openapi.json
index 36255184f4..d5846cca65 100644
--- a/docs/api-reference/openapi.json
+++ b/docs/api-reference/openapi.json
@@ -12732,6 +12732,15 @@
"type": "string",
"nullable": true,
"title": "Finally Block Label"
+ },
+ "error_code_mapping": {
+ "type": "object",
+ "nullable": true,
+ "title": "Error Code Mapping",
+ "description": "A mapping of custom error codes to natural-language descriptions applied at the workflow level. Block-level mappings override workflow-level entries for the same key.",
+ "additionalProperties": {
+ "type": "string"
+ }
}
},
"type": "object",
@@ -12910,6 +12919,15 @@
"type": "string",
"nullable": true,
"title": "Finally Block Label"
+ },
+ "error_code_mapping": {
+ "type": "object",
+ "nullable": true,
+ "title": "Error Code Mapping",
+ "description": "A mapping of custom error codes to natural-language descriptions applied at the workflow level. Block-level mappings override workflow-level entries for the same key.",
+ "additionalProperties": {
+ "type": "string"
+ }
}
},
"type": "object",
@@ -13729,4 +13747,4 @@
"url": "http://localhost:8000"
}
]
-}
\ No newline at end of file
+}
diff --git a/docs/going-to-production/error-handling.mdx b/docs/going-to-production/error-handling.mdx
index 6df479ffdb..33afde4219 100644
--- a/docs/going-to-production/error-handling.mdx
+++ b/docs/going-to-production/error-handling.mdx
@@ -380,7 +380,54 @@ curl -X POST "https://api.skyvern.com/v1/run/tasks" \
### In workflows
-Add `error_code_mapping` to individual blocks (navigation, task, validation):
+You can define `error_code_mapping` at two levels:
+
+- **Workflow level** — applies to every block in the workflow.
+- **Block level** — applies only to that block. When a block defines a mapping for the same key as the workflow, the block-level value takes precedence.
+
+This lets you set shared error codes once at the workflow level and override them on specific blocks when needed.
+
+#### Workflow-level mapping
+
+Add `error_code_mapping` at the top of the workflow definition, next to `parameters` and `blocks`:
+
+
+```json JSON
+{
+ "parameters": [],
+ "error_code_mapping": {
+ "maintenance": "The website is down for maintenance or unavailable",
+ "session_expired": "The session has expired or timed out"
+ },
+ "blocks": [
+ {
+ "block_type": "navigation",
+ "label": "login_step",
+ "url": "https://vendor-portal.example.com/login",
+ "navigation_goal": "Log in using the stored credentials"
+ }
+ ]
+}
+```
+
+```yaml YAML
+parameters: []
+error_code_mapping:
+ maintenance: "The website is down for maintenance or unavailable"
+ session_expired: "The session has expired or timed out"
+blocks:
+ - block_type: navigation
+ label: login_step
+ url: "https://vendor-portal.example.com/login"
+ navigation_goal: "Log in using the stored credentials"
+```
+
+
+Every block in this workflow inherits the `maintenance` and `session_expired` error codes without repeating them.
+
+#### Block-level mapping
+
+Add `error_code_mapping` to individual blocks (navigation, task, validation). Block-level entries override workflow-level entries for the same key:
The JSON examples below include comments (`//`) for clarity. Remove comments before using in actual workflow definitions—JSON does not support comments.
@@ -389,6 +436,9 @@ The JSON examples below include comments (`//`) for clarity. Remove comments bef
```json JSON
{
+ "error_code_mapping": {
+ "maintenance": "The website is down for maintenance or unavailable"
+ },
"blocks": [
{
"block_type": "navigation",
@@ -415,24 +465,30 @@ The JSON examples below include comments (`//`) for clarity. Remove comments bef
```
```yaml YAML
-- block_type: navigation
- label: login_step
- url: "https://vendor-portal.example.com/login"
- navigation_goal: "Log in using the stored credentials"
- error_code_mapping:
- login_failed: "Login credentials are incorrect or account is locked"
- mfa_required: "Two-factor authentication is being requested"
- captcha_blocked: "CAPTCHA is displayed and cannot be bypassed"
-
-- block_type: navigation
- label: download_invoice
- navigation_goal: "Download the invoice for {{invoice_date}}"
- error_code_mapping:
- invoice_not_found: "No invoice found for the specified date"
- download_failed: "Invoice exists but download button is broken or missing"
+error_code_mapping:
+ maintenance: "The website is down for maintenance or unavailable"
+
+blocks:
+ - block_type: navigation
+ label: login_step
+ url: "https://vendor-portal.example.com/login"
+ navigation_goal: "Log in using the stored credentials"
+ error_code_mapping:
+ login_failed: "Login credentials are incorrect or account is locked"
+ mfa_required: "Two-factor authentication is being requested"
+ captcha_blocked: "CAPTCHA is displayed and cannot be bypassed"
+
+ - block_type: navigation
+ label: download_invoice
+ navigation_goal: "Download the invoice for {{invoice_date}}"
+ error_code_mapping:
+ invoice_not_found: "No invoice found for the specified date"
+ download_failed: "Invoice exists but download button is broken or missing"
```
+In this example, both blocks inherit the workflow-level `maintenance` code and add their own block-specific codes. If `login_step` also defined `maintenance`, its block-level value would take precedence over the workflow-level one.
+
### Where the error code appears
When a mapped error occurs, your code appears in `output.error`. This field is available in both polling responses and webhook payloads:
diff --git a/docs/multi-step-automations/workflow-blocks-reference.mdx b/docs/multi-step-automations/workflow-blocks-reference.mdx
index caf35b1200..cd96946b9e 100644
--- a/docs/multi-step-automations/workflow-blocks-reference.mdx
+++ b/docs/multi-step-automations/workflow-blocks-reference.mdx
@@ -94,6 +94,8 @@ The referenced block must be a terminal block — it cannot have a `next_block_l
Several blocks accept an `error_code_mapping` parameter. This is an object mapping custom error codes to natural language descriptions. Skyvern evaluates each description against the current page state and surfaces matching errors in the block output.
+You can also define `error_code_mapping` at the **workflow level** (alongside `parameters` and `blocks`). Workflow-level mappings are inherited by every block. When a block defines the same key, the block-level value takes precedence. See the [error handling guide](/going-to-production/error-handling#in-workflows) for full examples.
+
```json
{
"error_code_mapping": {