Skip to main content
Use this guide to understand error responses, decide when to retry, and troubleshoot issues quickly.

Error response format

Errors use an RFC 7807 style shape.
{
  "type": "https://embed.nova.dweet.com/errors/validation-error",
  "code": "VALIDATION_ERROR",
  "status": 400,
  "message": "Request validation failed",
  "retryable": false,
  "traceId": "5c2f4f5b2c0a4ce0b6a31a1a18f8e9a1",
  "details": [
    {
      "field": "resumeUrl",
      "code": "invalid",
      "message": "Resume URL must be a valid URL"
    }
  ]
}
FieldDescription
typeURI reference identifying the error type
codeMachine-readable error code
statusHTTP status code
messageHuman-readable summary
retryableWhether retrying may succeed
traceIdTrace ID for debugging
detailsField-level validation errors (when present)
Every response includes an X-Trace-Id header. Error responses also include the same value as traceId.

When to retry

Use these rules:
  • If retryable is true, retry with exponential backoff.
  • If you get 429 RATE_LIMITED, wait for the Retry-After header.
  • Do not retry most 4xx errors until you fix the request.

Common error codes

Authentication

CodeStatusWhat to do
UNAUTHORIZED401Check your API key and Authorization header

Validation

CodeStatusWhat to do
VALIDATION_ERROR400Fix the fields listed in details
ANSWER_MISMATCH400Ensure your answers match the question set

Not found

CodeStatusWhat to do
CRITERIA_NOT_FOUND404Generate criteria for the job first
SCORING_JOB_NOT_FOUND404Verify the scoringJobId exists for this tenant
BATCH_NOT_FOUND404Verify the scoringBatchId exists for this tenant
LIBRARY_CRITERION_NOT_FOUND404Verify the criterionId exists for this tenant

Resume issues

CodeStatusWhat to do
RESUME_FETCH_FAILED422Check the resume URL is accessible and not expired
RESUME_TOO_LARGE422Reduce file size below 50 MB
RESUME_ENCRYPTED422Remove password protection from the PDF
RESUME_EMPTY422Provide a non-empty resume file
RESUME_PARSE_FAILED422Ensure the file is a valid PDF, DOC, or DOCX
TIMEOUT504Resume download took too long; try a faster source

Rate limiting

CodeStatusWhat to do
RATE_LIMITED429Wait for Retry-After and retry

Example retry logic

async function novaRequest(url, { method, headers, body }) {
  const maxAttempts = 3;

  for (let attempt = 1; attempt <= maxAttempts; attempt++) {
    const response = await fetch(url, {
      method,
      headers,
      body: body ? JSON.stringify(body) : undefined,
    });

    if (response.ok) {
      return response.json();
    }

    const error = await response.json();

    if (response.status === 429) {
      const retryAfterSeconds = Number(response.headers.get("Retry-After") ?? "60");
      await new Promise((r) => setTimeout(r, retryAfterSeconds * 1000));
      continue;
    }

    if (error.retryable && attempt < maxAttempts) {
      const delayMs = 250 * Math.pow(2, attempt - 1);
      await new Promise((r) => setTimeout(r, delayMs));
      continue;
    }

    throw Object.assign(new Error(error.message), { error });
  }
}

Debugging

When contacting support, include:
  • traceId from the error response
  • Your timestamp and endpoint
  • The HTTP status code