Error handling
Catch and respond to invalid tokens, bad requests, missing resources, and rate limits on the Scalekit REST API.
Catch and respond to invalid tokens, bad requests, missing resources, and rate limits.
A failed REST call returns an HTTP status and a JSON body. Official SDKs raise typed exceptions for the same failures. Use the body, or the exception fields, to choose a response.
For the endpoint catalog, open the API reference. Product catalogs live at SaaSKit APIs and AgentKit APIs.
Read the error body
Section titled “Read the error body”| Field | Meaning |
|---|---|
code | gRPC (remote procedure call) status number. This is not the HTTP status. Example: 16 means Unauthenticated. |
message | Human-readable reason. Safe for logs. Do not show raw messages to end users. |
details[].error_code | Stable slug to switch on, such as UNAUTHENTICATED. |
details[].validation_error_info | Present on some 400 responses. Lists field violations (field, description, constraint). |
details[].tool_error_info | Present when a tool call fails. Includes execution_id, tool_error_message, and tool_error_code. |
details[].help_info | Optional documentation links when the server attaches them. |
Scalekit does not return a request ID or a dashboard log URL in this envelope.
{ "code": 16, "message": "Token empty", "details": [ { "@type": "type.googleapis.com/scalekit.v1.errdetails.ErrorInfo", "error_code": "UNAUTHENTICATED" } ]}Switch on details[].error_code. Do not switch on code alone.
HTTP status codes
Section titled “HTTP status codes”- Codes in the
2xxrange mean success. - Codes in the
4xxrange mean the request failed given the data you sent. Fix the request. Do not retry the same payload, except for429. - Codes in the
5xxrange mean a server fault. Retry with backoff. Treat the result as unknown until a later call succeeds.
| HTTP | Typical error_code | Meaning |
|---|---|---|
200 / 201 | n/a | Success |
400 | INVALID_ARGUMENT, BAD_REQUEST | Invalid request or validation failure |
401 | UNAUTHENTICATED | Missing or invalid bearer token |
403 | PERMISSION_DENIED, FORBIDDEN | Authenticated, but not allowed |
404 | NOT_FOUND, RESOURCE_NOT_FOUND | Resource does not exist |
409 | RESOURCE_ALREADY_EXISTS | Duplicate resource |
429 | RATE_LIMITED, TOO_MANY_REQUESTS | Rate limit exceeded |
500 | INTERNAL_ERROR | Server error |
Catch exceptions
Section titled “Catch exceptions”SDKs translate non-success HTTP responses into exceptions. Catch the specific type first, then fall back to the base server exception.
import { ScalekitNotFoundException, ScalekitUnauthorizedException, ScalekitTooManyRequestsException, ScalekitServerException,} from '@scalekit-sdk/node'
try { // Your Scalekit SDK call await scalekit.organization.listOrganization({ pageSize: 30 })} catch (err) { if (err instanceof ScalekitUnauthorizedException) { // Get a new access token. Do not retry the same bearer token. } else if (err instanceof ScalekitNotFoundException) { // Create the resource or return not-found to the caller. } else if (err instanceof ScalekitTooManyRequestsException) { // Back off. Read err.errorCode: RATE_LIMITED vs TOOL_ERROR. } else if (err instanceof ScalekitServerException) { // Log err.message and err.errorCode. Retry only on 5xx or 429. } else { throw err }}from scalekit.common.exceptions import ( ScalekitNotFoundException, ScalekitUnauthorizedException, ScalekitTooManyRequestsException, ScalekitServerException,)
try: # Your Scalekit SDK call scalekit_client.organization.list_organizations(page_size=30)except ScalekitUnauthorizedException: # Get a new access token. Do not retry the same bearer token. passexcept ScalekitNotFoundException: # Create the resource or return not-found to the caller. passexcept ScalekitTooManyRequestsException as e: # Back off. Read e.error_code: RATE_LIMITED vs TOOL_ERROR. print(e.error_code, e.message)except ScalekitServerException as e: # Log e.message and e.error_code. Retry only on 5xx or 429. print(e.error_code, e.http_status)_, err := scalekitClient.Organization().ListOrganization(ctx, &scalekit.ListOrganizationOptions{ PageSize: 30,})if err != nil { // Inspect the error. Retry only on HTTP 429 or 5xx. // Do not retry the same payload on 400, 401, 403, 404, or 409. log.Printf("scalekit API error: %v", err) return err}try { scalekitClient.organizations().listOrganizations(30, "");} catch (ScalekitException error) { // Inspect the error. Retry only on HTTP 429 or 5xx. // Do not retry the same payload on 400, 401, 403, 404, or 409. System.err.println(error.getMessage());}Typed exception names and tool-specific types are listed on AgentKit Node error handling and AgentKit Python error handling.
Choose a response
Section titled “Choose a response”error_code | Problem | What to do |
|---|---|---|
UNAUTHENTICATED | Missing header (Token empty), bad Bearer value (Invalid Token), or expired token (token expired) | Request a new token. Do not retry the same token. See Authenticate with the Scalekit API. |
INVALID_ARGUMENT / BAD_REQUEST | The request is malformed or fails validation | Fix the fields. Do not retry the same payload. |
PERMISSION_DENIED / FORBIDDEN | The caller is authenticated but not allowed | Change roles, scopes, or the target resource. |
NOT_FOUND / RESOURCE_NOT_FOUND | The resource does not exist | Create it, or return not-found to your user. |
RESOURCE_ALREADY_EXISTS | A create conflicts with an existing resource | Use the existing ID, or pick a new unique value. |
RATE_LIMITED / TOO_MANY_REQUESTS | A Scalekit service rejected the call | Back off, then retry. See API rate limits. |
TOOL_ERROR | A tool call failed | Read tool_error_info.tool_error_code. An inner RATE_LIMITED is the upstream provider. |
INTERNAL_ERROR | A server fault | Retry with backoff. Treat the result as unknown until a later call succeeds. |
/api/v1 accepts a bearer access token from client credentials. It does not accept an API key header.
Validation errors
Section titled “Validation errors”Some 400 responses include validation_error_info.field_violations. Each violation names the field, a description, and the constraint that failed. The JSON below is an example of that shape.
{ "code": 3, "message": "Validation error", "details": [ { "@type": "type.googleapis.com/scalekit.v1.errdetails.ErrorInfo", "error_code": "INVALID_ARGUMENT", "validation_error_info": { "field_violations": [ { "field": "page_size", "description": "value must be less than or equal to 30", "constraint": "lte" } ] } } ]}Tool errors
Section titled “Tool errors”Tool execution sets the outer error_code to TOOL_ERROR. The inner slug is tool_error_info.tool_error_code. An upstream provider 429 still returns HTTP 429.
{ "code": 8, "message": "tool execution failed - rate limited", "details": [ { "@type": "type.googleapis.com/scalekit.v1.errdetails.ErrorInfo", "error_code": "TOOL_ERROR", "tool_error_info": { "execution_id": "exec_123", "tool_error_message": "rate limit", "tool_error_code": "RATE_LIMITED" } } ]}Read the outer code first. Then read tool_error_info.tool_error_code when the outer code is TOOL_ERROR.
Handle 429s
Section titled “Handle 429s”When a service exceeds its limit, Scalekit returns HTTP 429. The response body uses the same error envelope.
Outer error_code | Meaning |
|---|---|
RATE_LIMITED | A Scalekit service rejected the call |
TOO_MANY_REQUESTS | Email, one-time password (OTP), or time-based one-time password (TOTP) traffic hit a limit |
TOOL_ERROR with inner tool_error_code RATE_LIMITED | The upstream provider rate-limited the tool call |
Back off and retry with exponential backoff. Do not retry immediately.
Scalekit does not send a Retry-After header on 429 responses. Limits vary by service and account. For 429 handling in the SDKs, see API rate limits.
Fix common 400s
Section titled “Fix common 400s”Some 400 INVALID_ARGUMENT responses come from list and lookup URLs.
| Case | HTTP | error_code | Message |
|---|---|---|---|
Bad page_token | 400 | INVALID_ARGUMENT | invalid page token or Invalid cursor |
:external path plus an id query | 400 | INVALID_ARGUMENT | ExternalId is required |
Fix the URL or the query. Do not retry the same request.
For list parameters, see the operation in the API reference. For external IDs, see organization identifiers.