GraphQL mutation error recovery
Mutation execution with validation, failure paths, and rollback handling.
GraphQL mutations are powerful — a single request can validate input, check permissions, update the database, and return the new state — but they're also failure-prone. Validation can fail, permissions can deny, the database can reject the change, or the connection can drop mid-commit. This template lays out a nine-node flow: input validation, permission check, mutation execution, commit-or-rollback, and the paths back to the client for both success and failure.
The key insight is that each decision diamond is a place where the mutation must recover: invalid input returns errors to the client immediately, permission denied never touches the database (a security win), and database failures trigger a rollback so the database never ends up half-updated. Teams that skip these steps end up debugging mysterious partial updates in production.
When to use this template
- Mutation specification — before writing resolver code, diagram the happy path and all error paths, so the whole team agrees on what can go wrong and how the API should respond.
- Error message design — each error path in this diagram should return a specific, actionable error code to the client. Use this diagram to enumerate all the errors your mutation can return.
- Rollback strategy review — when designing mutations that touch multiple tables, use this diagram to make sure every database operation is wrapped in a transaction and every failure path triggers a rollback.
How to adapt it
Rename the input types and database operations to your real schema:
- Add side-effect handling — if the mutation sends an email or posts to Slack on success, add a step after 'Update cache' that executes the side effect, with a branch for side-effect failures that don't roll back the primary mutation.
- Include rate limiting — add a check after permissions and before database execution that verifies the user hasn't exceeded their mutation quota for the day.
- Add idempotency key verification — if the mutation is idempotent, add a check at the start to see if it was already executed, and return the cached result instead of running twice.
Visual edits regenerate clean code, so you can sketch different validation and rollback strategies in the editor without writing GraphQL-specific syntax directly.
Mermaid code
Copy it anywhere Mermaid is supported — GitHub, Notion, or your docs.
flowchart TD
A[Client sends mutation] --> B[Validate input schema]
B --> C{Input valid?}
C -->|No| D[Return validation errors]
D --> A
C -->|Yes| E[Check permissions]
E --> F{User authorized?}
F -->|No| G[Return permission denied]
G --> A
F -->|Yes| H[Execute mutation]
H --> I{Database commit succeeds?}
I -->|No| J[Rollback transaction]
J --> K[Return error with reason]
K --> A
I -->|Yes| L[Update cache]
L --> M[Return mutation result]
Frequently asked questions
- What is a GraphQL mutation error recovery diagram?
- It shows the journey of a GraphQL mutation from submission through validation, permission checks, database execution, and error recovery. It makes visible where mutations can fail — bad input, insufficient permissions, or database constraints — and what happens when they do: validation errors are returned immediately, permission errors are caught before the database is touched, and database failures trigger a rollback. Teams use it to design error messages and rollback strategies.
- Why is the permission check separate from validation?
- Validation is about shape and type (is the email a valid email?). Permissions are about policy (does the user own this resource?). Separating them means you fail fast on bad input before checking permissions, which also improves security — you don't leak information about whether a resource exists if the user can't access it. Reorder the nodes if your API has different requirements.
- What happens if the database commit fails?
- A rollback reverses any changes made during the mutation, leaving the database in its original state. The mutation then returns an error to the client with a reason (constraint violation, connection timeout, out of disk space). The client can retry the mutation later, update the input, or alert the user. The important part is: no partial updates, no silent failures.
- How do I handle optimistic updates or cache invalidation?
- After a successful mutation, you update the client-side cache so the UI reflects the change immediately — this is the 'Update cache' node. GraphQL clients like Apollo do this automatically if you return the full object. For complex mutations affecting multiple cached queries, add explicit cache invalidation (e.g. clear the user's profile cache, refetch the user list). Visual edits regenerate clean code, so you can sketch these extensions without touching syntax.
Related templates
API error handling flow
Client-side error handling strategies for API requests and failures.
Bulk data import pipeline
CSV upload, validation, transformation, database load with rollback on error.
Error handling and recovery flow
API error response paths and recovery strategies.