---
title: Troubleshooting
url: https://docs.schemalabs.ai/troubleshooting
description: Every response the Schema API returns when something needs your attention, what it is telling you, and the concrete next step.
---

# Troubleshooting

> Every response the Schema API returns when something needs your attention, what it is telling you, and the concrete next step.

Every non-2xx response carries one envelope with a machine-readable `error.type` and a `request_id` (see [Errors](https://docs.schemalabs.ai/api-reference#errors)). Branch on the type; quote the `request_id` to [support](https://docs.schemalabs.ai/support).

## What does each response mean?

| What you see | What to do |
|---|---|
| `400 validation_error` on `POST /v2/serve/:id` | The message names the table or column that differs from the pinned snapshot. Send table ids and columns that match the endpoint's data, or sync the source and refresh the endpoint onto the new schema. |
| `401 auth_error` | The key is missing, malformed, or revoked. Create a key on the platform's API page and send it as `Authorization: Bearer`. |
| `403 auth_error` | The key lacks the route's scope. Use a key with `read`, `run`, `serve`, `manage`, or `delete` as the route requires (see [Authentication](https://docs.schemalabs.ai/authentication)). |
| `404 not_found` | Check the id. Routes accept an endpoint id or its name; only the id survives a rename. |
| `409 conflict` with `running_job_id` | A refresh or upgrade is already running on that endpoint. Wait for the job, or cancel it with `POST /v2/jobs/:id/cancel`, then resubmit. |
| `409 conflict` on a retried POST | The `Idempotency-Key` was reused with a different body. Use a new key for a new request. |
| `422 capability_unavailable` | The base named in the request has been retired. Omit `base` to use the latest model, or move the endpoint with `POST /v2/endpoints/:id/upgrade` (see [Models](https://docs.schemalabs.ai/models)). |
| `429 rate_limit` | Wait for `Retry-After` and retry. Send large passes with `"options": { "processing": "batch" }` (see [Rate limits](https://docs.schemalabs.ai/billing#rate-limits)). |
| Job `status: "failed"` | Read `error` on the job object and resubmit. Failed jobs bill nothing. |
| Job `status: "expired"` | A batch job missed its completion window. Resubmit as batch, or with the default `realtime` processing; expired jobs bill nothing. |

## What does each result mean?

| What you see | What to do |
|---|---|
| `held_out.low_confidence: true` | `low_confidence_reason` names the cause: a small test partition or a target that is mostly missing. Add rows, or name a target with more values, then refresh. See [Held-out reports](https://docs.schemalabs.ai/held-out). |
| `target_selection` picked a column you did not intend | Set `target.column` (as `table.column`) and, for a numeric target, `task.type: "regression"`. On a text-only table, always name the target. |
| `prediction: null` | The request used `target.mode: "none"`, the understanding-only configuration. Set a target to get the prediction slice. |
| `held_out: null` on a prediction | A quick run prediction is in-context and carries `held_out: null`. Create an endpoint on the same configuration for a scored, servable prediction. |
| Few or no `entity_matches` | The tables need to describe the same entities and share at least one attribute (a phone, a name, a date). Lower `options.confidence_threshold` to see lower-confidence candidates, and check the `column_alignment` list first. |
| A `sector` you did not expect | Read `sector.top5` and the confidence on each entry. Detection is sector-agnostic and understands the values in the table. |
| An imputed value looks wrong | `imputation.row_confidence` scores each filled row. Gate on it in your pipeline, and keep the original cells; imputation never overwrites your data. |
