The unified error response format, error types, and troubleshooting practices for the Qoder Cloud Agents API.
The 401 authentication error uses a different response structure from other HTTP error codes. See 401 — Authentication Error for the confirmed format.
KE verification needed: Whether error codes 400, 403, 404, 409, and 500 also use the {"code":"...","message":"...","timestamp":"..."} structure has not been confirmed. The envelope definition below applies to those error codes pending verification.
For error codes other than 401, error responses follow this JSON structure:
{
"type": "error",
"error": {
"type": "<error_type>",
"message": "<human-readable error description>",
"param": "<name of the request parameter that triggered the error (optional)>"
}
}
Field descriptions
| Field | Type | Required | Description |
|---|
| type | string | Yes | Always"error" |
| error.type | string | Yes | Error type identifier |
| error.message | string | Yes | Human-readable error description |
| error.param | string | No | Name of the request parameter that triggered the error |
Error types overview
| HTTP status code | Error identifier | Description |
|---|
| 400 | error.type:invalid_request_error | Invalid or missing request parameters |
| 401 | code:TOKEN_INVALID | Authentication failed; the token is invalid or missing |
| 403 | error.type:permission_error | Authentication succeeded but access to the target resource is denied |
| 404 | error.type:not_found_error | The target resource does not exist |
| 409 | error.type:conflict_error | Resource state conflict (for example, duplicate creation) |
| 500 | error.type:api_error | Internal server error |
Error type details
400 — invalid_request_error
The request format or parameters are invalid.
Common triggers:
- Missing required field (for example, name)
- Incorrect field value type (for example, a number provided where a string is expected)
- Request body exceeds the 4 MB size limit
- Malformed JSON
{
"type": "error",
"error": {
"type": "invalid_request_error",
"message": "Missing required field: name",
"param": "name"
}
}
# Trigger example: missing the name field
curl -X POST "https://api.qoder.com.cn/api/v1/cloud/agents" \
-H "Authorization: Bearer $QODER_PAT" \
-H "Content-Type: application/json" \
-d '{}'
401 — Authentication Error
Authentication failed.
Common triggers:
- No Authorization header provided
- Malformed PAT format
- Expired or revoked PAT
- Using x-api-key instead of a Bearer Token
{
"code": "TOKEN_INVALID",
"message": "invalid pt-token",
"timestamp": "1782950157223"
}
# Trigger example: using an invalid token
curl -s "https://api.qoder.com.cn/api/v1/cloud/agents" \
-H "Authorization: Bearer pt-invalid-token"
403 — permission_error
Authentication succeeded but you do not have the required permissions.
Common triggers:
- The PAT has no access to the target Agent (it belongs to another user or organization)
- The PAT's permission scope does not cover the current operation
- Attempting to operate on an archived and locked resource
{
"type": "error",
"error": {
"type": "permission_error",
"message": "You do not have permission to access this agent."
}
}
# Trigger example: accessing another user's Agent
curl -s "https://api.qoder.com.cn/api/v1/cloud/agents/agent_other_user_123" \
-H "Authorization: Bearer $QODER_PAT"
404 — not_found_error
The target resource does not exist.
Common triggers:
- Agent/Session/Environment ID does not exist
- Resource has been deleted
- Typo in the URL path
{
"type": "error",
"error": {
"type": "not_found_error",
"message": "Agent not found: agent_nonexistent_123"
}
}
# Trigger example: querying a non-existent Agent
curl -s "https://api.qoder.com.cn/api/v1/cloud/agents/agent_nonexistent_123" \
-H "Authorization: Bearer $QODER_PAT"
409 — conflict_error
Resource state conflict; the operation cannot be executed.
Common triggers:
- A repeated request using the same idempotency key but a different request body
- Attempting to continue operating on an already-terminated Session
- Attempting to create a resource with a name that already exists
{
"type": "error",
"error": {
"type": "conflict_error",
"message": "A request with this idempotency key has already been processed with different parameters."
}
}
500 — api_error
Internal server error.
Common triggers:
- Service temporarily unavailable
- Internal component exception
- Database connection timeout
{
"type": "error",
"error": {
"type": "api_error",
"message": "An internal error occurred. Please try again later."
}
}
When a 500 error occurs, use an exponential backoff strategy for retries (wait 1s → 2s → 4s).
Error handling best practices
- Parse the error identifier for programmatic error handling rather than relying solely on HTTP status codes. For 401 errors, parse the code field; for all other errors, parse error.type.
- Logerror.message for troubleshooting.
- Checkerror.param to quickly locate the problematic field.
- Do not retry 4xx errors (unless you have modified the request parameters).
- Use backoff retry for 5xx errors (maximum 3 retries).
# Example request with error handling
response=$(curl -s -w "\n%{http_code}" \
"https://api.qoder.com.cn/api/v1/cloud/agents" \
-H "Authorization: Bearer $QODER_PAT")
# Extract HTTP status code
http_code=$(echo "$response" | tail -1)
body=$(echo "$response" | sed '$d')
if [ "$http_code" -ge 400 ]; then
if [ "$http_code" -eq 401 ]; then
# 401 uses the 'code' field; 'error.type' is not present
error_code=$(echo "$body" | python3 -c "import sys,json; print(json.load(sys.stdin)['code'])")
echo "Authentication error: $error_code"
else
error_type=$(echo "$body" | python3 -c "import sys,json; print(json.load(sys.stdin)['error']['type'])")
echo "API error: $error_type"
fi
fi