From attio-pack
Diagnoses and fixes common Attio REST API errors by HTTP status code using real response formats, error codes, causes, and curl diagnostics.
How this skill is triggered — by the user, by Claude, or both
Slash command
/attio-pack:attio-common-errorsThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Every Attio API error returns a consistent JSON body. This skill covers the real error codes, response format, and proven solutions for each.
Every Attio API error returns a consistent JSON body. This skill covers the real error codes, response format, and proven solutions for each.
All errors from https://api.attio.com/v2 return this structure:
{
"status_code": 429,
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded, please try again later"
}
Fields: status_code (HTTP status), type (error category), code (specific code), message (human-readable).
invalid_request{ "status_code": 400, "type": "invalid_request_error", "code": "invalid_request", "message": "..." }
Common causes and fixes:
| Message pattern | Cause | Fix |
|---|---|---|
Invalid value for attribute | Wrong type for attribute slug | Check attribute type with GET /v2/objects/{obj}/attributes |
Cannot query historic values | Used history param on unsupported type | Remove show_historic for that attribute |
Missing required field | Required attribute not provided | Check is_required on attribute definition |
Invalid filter format | Malformed filter object | Use shorthand { "email": "x" } or verbose { "$and": [...] } |
Diagnostic:
# List attributes to verify types
curl -s https://api.attio.com/v2/objects/people/attributes \
-H "Authorization: Bearer ${ATTIO_API_KEY}" \
| jq '.data[] | {slug: .api_slug, type: .type, required: .is_required}'
authentication_error{ "status_code": 401, "type": "authentication_error", "code": "invalid_api_key", "message": "..." }
| Cause | Fix |
|---|---|
Missing Authorization header | Add Authorization: Bearer sk_... |
| Token revoked or deleted | Generate new token in Attio dashboard |
| Malformed header | Ensure format is Bearer <token> (one space, no quotes) |
Diagnostic:
# Verify token works
curl -s -o /dev/null -w "%{http_code}" \
https://api.attio.com/v2/objects \
-H "Authorization: Bearer ${ATTIO_API_KEY}"
# Should return 200
insufficient_scopes{ "status_code": 403, "type": "authorization_error", "code": "insufficient_scopes",
"message": "Token requires 'record_permission:read-write' scope" }
| Operation | Required scopes |
|---|---|
| List/get records | object_configuration:read + record_permission:read |
| Create/update records | object_configuration:read + record_permission:read-write |
| List entries | object_configuration:read + record_permission:read + list_entry:read |
| Create/update entries | Above + list_entry:read-write |
| Create notes | note:read-write + object_configuration:read + record_permission:read |
| List tasks | task:read + object_configuration:read + record_permission:read + user_management:read |
| Manage webhooks | webhook:read-write |
Fix: Edit token in Settings > Developers > Access tokens, add missing scope, save. No need to regenerate.
not_found{ "status_code": 404, "type": "not_found_error", "code": "not_found", "message": "..." }
| Cause | Fix |
|---|---|
| Wrong object slug | Verify with GET /v2/objects -- use api_slug field |
| Invalid record_id | Record may have been deleted or merged |
| Wrong list slug | Verify with GET /v2/lists |
| Typo in endpoint path | Check path starts with /v2/ |
conflictOccurs when creating a record with a value that conflicts with an existing unique attribute (e.g., duplicate email or domain).
Fix: Use PUT (assert) instead of POST to upsert:
// Assert: create or update matching record
await client.put("/objects/people/records", {
data: {
values: {
email_addresses: ["[email protected]"],
name: [{ first_name: "Updated", last_name: "Name" }],
},
},
});
validation_error| Message pattern | Cause | Fix |
|---|---|---|
Invalid email address | Malformed email string | Validate email format before sending |
Invalid phone number | Not E.164 format | Prefix with country code: +14155551234 |
Unknown attribute | Attribute slug does not exist | List attributes first |
Invalid record reference | target_record_id doesn't exist | Verify record exists first |
rate_limit_exceeded{
"status_code": 429,
"type": "rate_limit_error",
"code": "rate_limit_exceeded",
"message": "Rate limit exceeded, please try again later"
}
Attio uses a sliding window algorithm with a 10-second window. The Retry-After response header contains a date (usually the next second).
Immediate fix:
if (res.status === 429) {
const retryAfter = res.headers.get("Retry-After");
const waitMs = retryAfter
? new Date(retryAfter).getTime() - Date.now()
: 1000;
await new Promise((r) => setTimeout(r, Math.max(waitMs, 100)));
// Retry the request
}
See attio-rate-limits for full backoff and queue patterns.
Rare, but Attio may reduce rate limits during incidents. Always implement retry for 5xx.
Check: status.attio.com
#!/bin/bash
echo "=== Attio Diagnostic ==="
echo -n "Auth: "
curl -s -o /dev/null -w "%{http_code}" \
https://api.attio.com/v2/objects \
-H "Authorization: Bearer ${ATTIO_API_KEY}"
echo ""
echo -n "Status page: "
curl -s https://status.attio.com/api/v2/status.json | jq -r '.status.description'
echo "Objects:"
curl -s https://api.attio.com/v2/objects \
-H "Authorization: Bearer ${ATTIO_API_KEY}" \
| jq -r '.data[].api_slug' 2>/dev/null || echo "FAILED"
import { AttioApiError } from "./client";
async function handleAttioError(err: AttioApiError): Promise<void> {
switch (err.statusCode) {
case 401: throw new Error("Attio auth failed -- check ATTIO_API_KEY");
case 403: throw new Error(`Missing scope: ${err.message}`);
case 404: console.warn("Resource not found, may have been deleted"); break;
case 409: console.warn("Conflict -- use PUT to upsert instead"); break;
case 429: /* handled by retry wrapper */ break;
default: throw err;
}
}
For evidence collection, see attio-debug-bundle. For retry patterns, see attio-rate-limits.
5plugins reuse this skill
First indexed Jul 10, 2026
npx claudepluginhub fleet-to-force/claude-code-plugins-plus --plugin attio-packDiagnose and fix common Attio REST API errors by HTTP status code (400, 401, 403, 422, 429). Provides real error response formats, codes, and proven fixes using curl.
Diagnoses and fixes SalesLoft API v2 errors: 401, 403, 422, 429, 5xx. Includes OAuth token troubleshooting and rate limit handling.
Guides collaborative design exploration before implementation: explores context, asks clarifying questions, proposes approaches, and writes a design doc for user approval.