Handle errors in a client
This guide shows you how to parse error responses from the Exofind API, route failures by status code, inspect refused input fields, and safely retry or recover failed requests. Use this guide when building an API client or integration.
For the complete list of error codes and prefixes, see Errors. For details on status code semantics across endpoints, see API conventions.
Prerequisites
Section titled “Prerequisites”Before handling errors, ensure your client can:
- Make HTTP requests to an Exofind endpoint under
/v1alpha1. - Parse JSON response bodies.
Read the error body and match on the code
Section titled “Read the error body and match on the code”Every failed request returns an application/json payload with a top-level code, a human-readable message, and an errors array.
- Parse the JSON response body when the HTTP status is
4xxor5xx. - Inspect the machine-readable
codefield instead of themessagestring. Themessagestring is intended for logs and can change, whereascodevalues remain stable across versions. - If your client encounters an unknown code under a known namespace prefix (such as an unfamiliar
index:field:*code), handle it using the fallback behavior for that prefix.
An error response uses the following structure:
{ "code": "validation", "message": "Request contains 2 errors", "errors": [ { "code": "index:field:primary_key:multiple_unsupported", "message": "Field `id` is marked as a primary key and multiple, primary keys can not have multiple values", "path": "id", "arguments": { "name": "id" } } ]}Locate refused input using path and arguments
Section titled “Locate refused input using path and arguments”When a request fails validation or contains bad field definitions, use the errors array to show your caller exactly what was refused.
- Iterate over the
errorslist in the response body. - Read the
pathproperty to locate the specific field or position in your payload that caused the failure. Ifpathis absent ornull, the error applies to the request as a whole. - Read the
argumentsmap to retrieve the specific values associated with the error code. Arguments are formatted as strings so you can construct custom, localized error messages without parsing English text.
Decide how to handle each HTTP status code
Section titled “Decide how to handle each HTTP status code”Categorize the failure by HTTP status code to determine whether to fix the request, retry, or reload state:
- Fix the request without retrying (
400,401,403,404):400 Bad Request: The payload or query is invalid. Fix the payload or query parameters before sending again.401 Unauthorized: The credential is missing, malformed, or invalid. Present a validAuthorization: Bearer <key>credential.403 Forbidden: The credential lacks permission for the requested action.404 Not Found: The resource does not exist, your credential has no access to the index, or no endpoint answers the path. Do not retry without changing the target resource path.405 Method Not Allowed: The path is not answered for the method you sent. Check the method against the REST API pages.406 Not Acceptable: Send anAcceptheader that allowsapplication/json.413 Content Too Large: The body is larger than the node accepts. Split it into smaller requests. The node closes the connection, so open a new one for the next request.415 Unsupported Media Type: Send aContent-Typethe endpoint reads, which isapplication/jsonon every endpoint and alsoapplication/x-ndjsonon the documents endpoints.
- Wait and retry the same request (
409,502,503):409 Conflict: The request is well-formed, but the deployment state currently prevents execution (for example, another reindex is running, or an indexer node is synchronizing). Wait and retry the request once state changes.502 Bad Gateway: The request was forwarded to the index writer node, but the writer did not respond. Retry the request.503 Service Unavailable: The node temporarily cannot serve the request (such as during index reopening or leadership lookups). Retry the request.
- Re-read and rebuild (
412):412 Precondition Failed: The version in yourIf-Matchheader no longer matches the storedETag. Fetch the latest version of the resource (GET), apply your intended changes onto the new version, and send the update with the newETag.
Retry safely based on request idempotency
Section titled “Retry safely based on request idempotency”When a network timeout occurs or the server returns 502 or 503, determine whether the request expresses desired state before repeating it:
- Full index definitions and document writes:
PUT /v1alpha1/admin/indexes/{name}and document indexing endpoints declare desired state. Documents carry their own primary keys and overwrite earlier versions. If a timeout occurs, you can resend the request without checking server state first. - Document removals: Removing a document by primary key states desired state. Resending the removal after a timeout is safe.
- Partial document updates:
POST /v1alpha1/indexes/{name}/documents/actions/updatedescribes modifications to an existing document rather than full state. Do not blindly repeat partial updates if a request times out; verify the document’s state first.
Recover from refused document batches
Section titled “Recover from refused document batches”When a batch write stops at a refused entry, entries processed before the failure stay in the index and commit with the rest.
- Read
positionfrom the errorargumentsto find the failed entry. - Read
processedfromargumentsto see how many entries landed in the index. - If you sent
application/x-ndjson, readlinefromargumentsto find the line where the entry starts. - Correct the invalid entry.
- Send the batch again. Resending an index batch is safe because indexing states desired state. A resumed update batch must start at
positionand not earlier because partial updates are not idempotent.
To process the full batch without stopping at the first refused entry, send the request with ?onError=skip. For more information, see Skipping refused entries.
Confirm the error handling
Section titled “Confirm the error handling”Verify that your client handles failure conditions as expected:
- Send a request with an invalid field name to confirm your client parses the
errorsarray, extractspathandarguments, and surfaces a400validation error without retrying. - Send a
PUTrequest with an outdatedIf-Matchheader to confirm your client detects412 Precondition Failed, fetches the freshETag, and reapplies the update. - Simulate a
503 Service Unavailableresponse to verify that your client waits and retries idempotent operations.
Related
Section titled “Related”- Errors - The error body and the code vocabulary.
- API conventions - Media types, conditional requests, forwarding, and what each status code means.
- Generating an API client - Building the client the error handling sits in.
- Indexing documents - Recovering from a refused batch.
- Testing an application against a node - Running the error paths against a node in a container.
- What a write guarantees - Which writes a failover can lose, and why a retry is safe.
- Operating a deployment - Telling a node that is behind from one that is broken.
Exofind is built by Level Four AB and is available under the Apache License 2.0.