Skip to content

Errors

This page documents all HTTP error codes and error response formats returned by the Nodexa API.


Error Response Format

All errors return a JSON body with a consistent structure:

{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "The provided API key is invalid or has been revoked."
  }
}
Field Type Description
error.type string Error category — see the type reference below
error.code string Machine-readable error code for programmatic handling
error.message string Human-readable description of the error

HTTP Status Codes

400 Bad Request

The request is malformed or contains invalid parameters.

error.code Description
invalid_request The request body is not valid JSON
missing_required_field A required field (model, input) is absent
invalid_model The model field is not a valid assistant UUID
tool_not_supported_for_model The tool type is not compatible with the backing LLM model
too_many_tools More than 128 tools were provided
duplicate_tool_name Two or more tools in the request have the same name
invalid_tool_name A tool name contains invalid characters or exceeds 64 chars
invalid_input_type An item in the input array has an unrecognized type or role
missing_call_id A function_call_output item is missing the call_id field

Example:

{
  "error": {
    "type": "invalid_request_error",
    "code": "too_many_tools",
    "message": "You provided 150 tools. The maximum is 128 per request."
  }
}

401 Unauthorized

Authentication failed. No API key was provided, or the key is not recognized.

error.code Description
missing_api_key Neither x-api-key nor Authorization header was provided
invalid_api_key The API key is malformed, expired, or has been revoked

Example:

{
  "error": {
    "type": "authentication_error",
    "code": "invalid_api_key",
    "message": "The provided API key is invalid or has been revoked."
  }
}

Checklist if you receive this error:

  • Verify your API key starts with nxk_
  • Ensure you are using the correct header (x-api-key or Authorization: Bearer)
  • Check that the key has not been revoked in the admin panel
  • Verify you are targeting the correct Nodexa instance URL

403 Forbidden

The API key is valid but does not have permission to access this endpoint.

error.code Description
insufficient_scope The key's scope does not include the required permission

Example:

{
  "error": {
    "type": "authentication_error",
    "code": "insufficient_scope",
    "message": "This API key requires the 'user' scope to access memory endpoints."
  }
}

Scope requirements:

Endpoint Required Scope
POST /v1/responses assistant or full_access
GET /user-claims/:userId user or full_access
POST /user-claims user or full_access
POST /user-claims/bulk user or full_access
DELETE /user-claims/:userId/:claimKey user or full_access
GET /v1/memory user or full_access
DELETE /v1/memory user or full_access
POST /v1/memory/opt-out user or full_access

404 Not Found

The requested resource does not exist.

error.code Description
assistant_not_found No assistant exists with the provided UUID
claim_not_found No claim exists for the given userId + claimKey combination
memory_item_not_found No memory item exists with the given ID
response_not_found The previous_response_id does not match any stored response

Example:

{
  "error": {
    "type": "not_found_error",
    "code": "assistant_not_found",
    "message": "No assistant found with ID 'asst_00000000-0000-0000-0000-000000000000'."
  }
}

422 Unprocessable Entity

The request is syntactically valid but fails semantic validation.

error.code Description
claim_value_too_large The claimValue exceeds the 64KB limit
bulk_limit_exceeded More than 50 claims were provided in a bulk request

503 Service Unavailable

The Nodexa platform or a downstream dependency is temporarily unavailable.

error.code Description
upstream_unavailable The LLM provider is unreachable or returned a service error
upstream_timeout The LLM provider did not respond within the timeout period
service_overloaded The platform is under high load; retry after a brief pause

Example:

{
  "error": {
    "type": "server_error",
    "code": "upstream_timeout",
    "message": "The LLM provider did not respond within the timeout period. Please try again."
  }
}

Retry with exponential backoff

For 503 errors, implement retry logic with exponential backoff:

```js
async function callWithRetry(fn, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (err) {
      if (err.status === 503 && attempt < maxRetries - 1) {
        const delay = Math.pow(2, attempt) * 1000; // 1s, 2s, 4s
        await new Promise(r => setTimeout(r, delay));
        continue;
      }
      throw err;
    }
  }
}
```

Error Types Reference

error.type Meaning
authentication_error Authentication or authorization failure
invalid_request_error Malformed or invalid request parameters
not_found_error The requested resource does not exist
validation_error Request is valid JSON but fails semantic validation
server_error Internal platform error or upstream provider failure

Streaming Errors

When stream: true, errors that occur after the stream has started are delivered as response.error events rather than HTTP error status codes (since the HTTP response has already started with 200).

{
  "type": "response.error",
  "error": {
    "type": "server_error",
    "code": "upstream_timeout",
    "message": "The LLM provider did not respond within the timeout period."
  }
}

After a response.error event, the stream closes. Always listen for this event in your stream handler:

for await (const event of stream) {
  if (event.type === 'response.error') {
    console.error('Stream error:', event.error.message);
    // Show error state in UI
    break;
  }
  // ... handle other events
}

Error Handling Best Practices

Check status before reading output_text

const response = await client.responses.create({ model, input });

if (response.status === 'requires_action') {
  // Handle tool calls — don't read output_text yet
} else if (response.status === 'completed') {
  console.log(response.output_text);
}

Handle 401 centrally

async function callNodexa(requestFn) {
  try {
    return await requestFn();
  } catch (err) {
    if (err.status === 401) {
      // API key invalid — log prominently, alert on-call
      console.error('CRITICAL: Nodexa API key invalid or revoked');
      throw err;
    }
    if (err.status === 503) {
      // Transient — safe to retry
      throw err;
    }
    throw err;
  }
}

Validate tool call results

// Always respond to tool calls, even on error
try {
  result = await myTool(args);
} catch (err) {
  result = { error: true, message: err.message };
}

toolResults.push({
  type: 'function_call_output',
  call_id: item.call_id,
  output: JSON.stringify(result), // always send something back
});