Files
ITWorx_MCP_Hub-Public/docs/04-mcp/ERROR_MODEL.md
T

61 lines
1.8 KiB
Markdown

# Error Model
## Stable categories
- `AUTHENTICATION_REQUIRED`
- `TOKEN_INVALID`
- `ACCESS_DENIED`
- `PROJECT_NOT_FOUND`
- `RESOURCE_NOT_REGISTERED`
- `CONNECTOR_DISABLED`
- `CONNECTOR_UNAVAILABLE`
- `TARGET_UNAVAILABLE`
- `VALIDATION_FAILED`
- `RATE_LIMITED`
- `TIMEOUT`
- `RESULT_TOO_LARGE`
- `UPSTREAM_PROTOCOL_ERROR`
- `INTERNAL_ERROR`
## Response rules
- do not reveal whether a forbidden resource exists when that leaks scope;
- include a trace ID;
- use retryability metadata;
- keep user-facing messages useful but sanitized;
- log detailed internal exceptions only in protected logs;
- translate target-specific errors into stable categories while preserving a safe diagnostic code.
- separate `retryable` from `safeToRetry`: transient writes may be retryable only
after their exact state is reconciled, never by blind transport replay;
- identify the failed operation and subsystem without returning target URLs,
credentials, raw headers or stack traces;
- include expected/actual state and a bounded recovery hint when optimistic state
changed;
- keep the stateless MCP session usable after an operation error.
Example:
```json
{
"error": {
"code": "CONNECTOR_UNAVAILABLE",
"category": "transient",
"message": "The Unraid inventory connector is temporarily unavailable.",
"operation": "unraid.container.health",
"subsystem": "upstream_unraid",
"retryable": true,
"safeToRetry": true,
"correlationId": "...",
"sessionId": null,
"upstreamStatus": 503,
"expectedState": null,
"actualState": null,
"recoveryHint": "Retry the unchanged read after the bounded backoff."
}
}
```
The dataplane retries only MCP protocol reads and catalogued R1 tools, once.
Connector-local Gitea GETs use at most three bounded attempts. R2, R3 and unknown
operations are never automatically retried.