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

# Troubleshooting

> Diagnose connectivity, authentication, scope, validation, state conflicts, throttling, timeouts, and download failures.

Start with the HTTP status, `error.code`, and `X-Request-ID`. Do not repeat writes blindly while diagnosing.

## Triage flow

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
flowchart TD
    A[Request failed] --> B{Can GET /health be reached?}
    B -- No --> C[Check DNS, TLS, firewall, proxy, and base URL]
    B -- Yes --> D{Protected read succeeds?}
    D -- No --> E{Status}
    E -->|401| F[Check key value and active status]
    E -->|403| G[Check tenant and key scope]
    E -->|400 / 406| H[Check headers and request ID]
    E -->|429| I[Honor Retry-After]
    E -->|5xx| J[Backoff and capture request ID]
    D -- Yes --> K{Write or download fails?}
    K -- Write --> L[Check schema, references, state, and dry run]
    K -- Download --> M[Check metadata, fileName, scope, and media type]
```

## Connectivity

| Symptom                                  | Check                                                                       |
| ---------------------------------------- | --------------------------------------------------------------------------- |
| DNS or connection failure                | Base URL is exactly `https://api.jobhandy.io/v1`; outbound HTTPS is allowed |
| TLS failure                              | System trust store, TLS inspection, proxy configuration, and current time   |
| `/health` fails                          | Network path or public service availability                                 |
| `/health` works but protected read fails | API key, tenant scope, or request headers                                   |

## Authentication and scope

### `401 INVALID_API_KEY`

* Confirm the value is loaded from the intended secret version.
* Confirm there are no leading/trailing spaces or accidental quotes.
* Confirm the key is active in API Key Management.
* Confirm a stale runtime was not missed during rotation.

### `403 TENANT_NOT_IN_SCOPE`

* Confirm `X-Tenant-ID` is a tenant ID, not a company name or division ID.
* Confirm the selected tenant is included in the key scope.
* Confirm the referenced resource belongs to the same authorized context.

### Ambiguous placement

Send `X-Tenant-ID` and, for employee creation where required, an allowed `divisionId`.

## Request validation

| Error                         | Check                                                                                                |
| ----------------------------- | ---------------------------------------------------------------------------------------------------- |
| `UNKNOWN_QUERY_PARAMETER`     | Parameter name and endpoint support                                                                  |
| `UNSUPPORTED_HEADER`          | Remove non-contract request headers                                                                  |
| `INVALID_FILTER_SYNTAX`       | Quotes, escaped apostrophes, parentheses, `IN` commas                                                |
| `UNSUPPORTED_FILTER_FIELD`    | Endpoint-specific field list                                                                         |
| `UNSUPPORTED_FILTER_OPERATOR` | Operator compatible with field                                                                       |
| `UNSUPPORTED_SORT_FIELD`      | Exactly one documented scalar field                                                                  |
| `UNSUPPORTED_MEDIA_TYPE`      | `application/json` or documented multipart type                                                      |
| `PAYLOAD_TOO_LARGE`           | Complete JSON or multipart body below 5 MiB                                                          |
| `VALIDATION_ERROR`            | Required fields, formats, enum case, nullability, unknown properties                                 |
| `EMPLOYEE_NOT_ACTIVATED`      | Referenced employee has not completed activation; activate the employee before creating the incident |

## State conflicts

For `409`, re-read the resource before taking action.

* `ORDER_ALREADY_DECIDED`: reconcile the current final decision.
* `INVALID_STATE_TRANSITION`: current lifecycle does not permit the request.
* `DIVISION_CYCLE`: selected parent is a descendant of the division.
* `DIVISION_NAME_NOT_UNIQUE_ON_SAME_LEVEL`: choose a unique sibling name.
* `DUPLICATE_RESOURCE`: find and map the existing resource.

## Timeout after a write

```mermaid theme={"theme":{"light":"github-light","dark":"github-dark"}}
flowchart TD
    A[Client timed out] --> B[Do not assume failure]
    B --> C[Read or search affected resource]
    C --> D{Desired result present?}
    D -- Yes --> E[Reconcile as success]
    D -- No --> F{Replay safe after state check?}
    F -- Yes --> G[Retry with new request ID]
    F -- No --> H[Manual resolution]
```

## Download failures

* Re-read metadata and confirm `fileName` is not `null`.
* Confirm the ID belongs to the expected tenant.
* Inspect status and `Content-Type` before writing to disk.
* Discard partial files after `502`, `503`, `504`, or network interruption.
* Retry transient download failures with bounded backoff.

## Escalation record

Collect:

```text theme={"theme":{"light":"github-light","dark":"github-dark"}}
UTC timestamp
method and path
HTTP status
error.code and error.message
X-Request-ID / error.requestId
tenant context
attempt count
whether dryRun was used
sanitized reproduction steps
```

Never include the API key or unnecessary complete personal payloads.
