> ## Documentation Index
> Fetch the complete documentation index at: https://surf-dcinside-api.kr.ask.surf/llms.txt
> Use this file to discover all available pages before exploring further.

# Errors

> Error body, status codes and what to do for each

<div style={{ maxWidth: 760 }}>
  <h2 style={{ fontSize: "22px", marginBottom: 8 }}>Error body</h2>

  Every error has the same JSON body:

  <ResponseField name="error" type="object" required>
    <Expandable title="properties">
      <ResponseField name="code" type="string" required>
        Machine-readable code from the table below.
      </ResponseField>

      <ResponseField name="message" type="string" required>
        Human-readable summary.
      </ResponseField>

      <ResponseField name="fields" type="array of objects">
        Every failing field, when the error is about the body. Each item has `path`, for example `candidates[0].created_at`, and `problem`.
      </ResponseField>
    </Expandable>
  </ResponseField>

  <Note>
    A `400` lists every failing path at once, not just the first, so one fix cycle is enough.
  </Note>

  ***

  <h2 style={{ fontSize: "22px", marginBottom: 8 }}>Status codes</h2>

  | Status | `code` | When | What happens |
  | - | - | - | - |
  | 400 | `bad_request` | The body is not valid JSON, or a field fails the schema. | Nothing stored, no scores. DCinside skips the cycle and fixes the field. |
  | 401 | `unauthorized` | API key missing or unknown. | As above. |
  | 403 | `forbidden` | The key has no scope for this call. | As above. |
  | 404 | `not_found` | `GET /v1/scores/{cycle_id}` for a cycle we never received. | Nothing to return. |
  | 409 | `cycle_conflict` | The cycle id was already used with a different body. | The first body stays. DCinside sends the next cycle under a new id. |
  | 409 | `version_conflict` | The weights version was already used with different weights. | The first weights stay. Send new weights under a new version. |
  | 413 | `too_large` | Over the size or row limits, or an image over the size limit. | Split the call, or ask us to raise the limit. |
  | 415 | `unsupported_media_type` | An image that is not a JPEG. | Nothing stored. |
  | 422 | `unprocessable` | The body matches the schema but the values are not acceptable: `cycle_time` off the grid or in the future, a post twice in one array, weights that are all zero. | Nothing stored. The previous weights stay in force. |
  | 429 | `rate_limited` | Too many calls. Comes with a `Retry-After` header. | Wait, then repeat the same call with the same id. |
  | 500, 503 | `server_error` | Our failure. | No scores. DCinside skips the cycle and our alert fires. |

  <Warning>
    A cycle that fails is skipped, not queued: the next cycle carries the current state, so nothing needs replaying. Only repeat a call with the **same** cycle id after a timeout or a `429`, because that id then returns the stored response instead of scoring twice.
  </Warning>
</div>
