> ## Documentation Index
> Fetch the complete documentation index at: https://docs.harborframework.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Error classification

> The single reference for how Harbor treats every trial error: retry, grade, and whether the reward counts.

[`error_policy.py`](https://github.com/harbor-framework/harbor/blob/main/src/harbor/models/trial/error_policy.py) is the **single source of truth** for trial errors. Every exception type maps to one cause, and the cause fixes three decisions that every part of Harbor follows: whether the trial is **retried**, whether the verifier still runs (**grade**), and whether the reward is **valid**. A valid reward is one that counts in benchmark and RL results, whether its value is 0 or 1. A trial with no error always has a valid reward. A trial with an error usually does not, but errors caused by the agent itself, such as running out of time, still produce a valid reward.

<img src="https://mintcdn.com/harborframework/eRnprZau8pCOPZNA/images/error-classification.png?fit=max&auto=format&n=eRnprZau8pCOPZNA&q=85&s=5e986a44765027cf9cb0b797ae12c3bc" alt="Error classification decision tree" width="1752" height="1616" data-path="images/error-classification.png" />

## Exception types

Generated from `_POLICY_GROUPS` in [`error_policy.py`](https://github.com/harbor-framework/harbor/blob/main/src/harbor/models/trial/error_policy.py). Exception types not listed are `unclassified`.

| Cause | Reward valid | Retry | Grade | Exception types |
| - | - | - | - | - |
| `agent_exhausted_budget` | Yes | No | Yes | `AgentTimeoutError`, `ContextWindowExceededError`, `OutputTokenExceededError`, `ContextLengthExceededError`, `OutputLengthExceededError` |
| `agent_refused_task` | Yes | No | Yes | `AgentSafetyRefusalError`, `ContentPolicyViolationError` |
| `sandbox_failed` | No | Yes | No | `EnvironmentStartTimeoutError`, `SandboxBuildFailedError`, `AgentSetupTimeoutError`, `HealthcheckError`, `SandboxLikelyOutOfMemoryError`, `MemoryLimitExceededError`, `SSHAccessError`, `GKEExecStreamClosedError`, `GKEPodNotFoundError`, `RuntimeRequestError`, `AddTestsDirError`, `DownloadVerifierDirError` |
| `model_provider_failed` | No | Yes | Yes | `ApiError`, `ApiRateLimitError`, `ApiInternalServerError`, `ApiOverloadedError`, `ApiConnectionClosedError`, `ApiResponseStalledError`, `UnknownApiError`, `NetworkConnectionError`, `ApiConnectionError`, `ApiUsageLimitError`, `RateLimitError`, `InternalServerError`, `ServiceUnavailableError`, `APIConnectionError`, `APIError`, `Timeout` |
| `model_provider_failed` | No | No | Yes | `BadRequestError`, `UnprocessableEntityError`, `UnsupportedParamsError`, `APIResponseValidationError`, `BudgetExceededError` |
| `model_provider_failed` | No | No | No | `AgentAuthenticationError`, `ModelNotFoundError`, `ApiProviderResourceNotFoundError`, `AuthenticationError`, `PermissionDeniedError`, `NotFoundError` |
| `harbor_failed` | No | No | No | `ServiceOperationsUnsupportedError`, `VercelScopeError`, `DspyImportError`, `MissingExtraError`, `RegradeError` |
| `unclassified` | No | Yes | Yes | `NonZeroAgentExitCodeError` |
| `verifier_failed` | No | No | Yes | `VerifierTimeoutError`, `RewardFileNotFoundError`, `RewardFileEmptyError`, `VerifierOutputParseError` |
| `cancelled` | No | No | No | `CancelledError` |

`retry.include_exceptions` and `retry.exclude_exceptions` in the [job config](/jobs/configs#retry) override the retry column per job.

## Reading the classification

```python theme={"system"}
result = TrialResult.model_validate_json(path.read_text())

result.exception_info.exception_type   # "ApiRateLimitError"
result.failure_cause                   # FailureCause.MODEL_PROVIDER_FAILED
result.reward_valid                    # False
```


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.