agentsclimarketplace

Attio common errors

Skill ComeOnOliver/skillshub/skills/jeremylongshore/claude-code-plugins-plus-skills/attio-common-errors

🧠 The right skill, one API call. AI agent skills registry with token-efficient skill resolution. 5,000+ skills from 500+ top repos.

Install
npx -y skills add ComeOnOliver/skillshub --skill attio-common-errors

Assembled from the repository path, not quoted from the project. Check it against their README if it does not work.

What its author says it does

Copied from the file, not written here

Diagnose and fix the top Attio REST API errors by HTTP status code. Real error response formats, actual error codes, and proven fixes. Trigger: "attio error", "fix attio", "attio not working", "attio 429", "attio 403", "attio 422", "debug attio".

The file declares its own license as MIT. That is the author’s claim about this one file, and it is not the same thing as the license GitHub reports for the repository, which is listed with the other numbers below.

SKILL.md

7.1 KB, ~1.8k tokens by cl100k_base, as published. Nobody here has run it

Attio Common Errors

Overview

Every Attio API error returns a consistent JSON body. This skill covers the real error codes, response format, and proven solutions for each.

Attio Error Response Format

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).

Error Reference

400 Bad Request -- invalid_request

{ "status_code": 400, "type": "invalid_request_error", "code": "invalid_request", "message": "..." }

Common causes and fixes:

Message patternCauseFix
Invalid value for attributeWrong type for attribute slugCheck attribute type with GET /v2/objects/{obj}/attributes
Cannot query historic valuesUsed history param on unsupported typeRemove show_historic for that attribute
Missing required fieldRequired attribute not providedCheck is_required on attribute definition
Invalid filter formatMalformed filter objectUse 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}'

401 Unauthorized -- authentication_error

{ "status_code": 401, "type": "authentication_error", "code": "invalid_api_key", "message": "..." }
CauseFix
Missing Authorization headerAdd Authorization: Bearer sk_...
Token revoked or deletedGenerate new token in Attio dashboard
Malformed headerEnsure 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

403 Forbidden -- insufficient_scopes

{ "status_code": 403, "type": "authorization_error", "code": "insufficient_scopes",
  "message": "Token requires 'record_permission:read-write' scope" }
OperationRequired scopes
List/get recordsobject_configuration:read + record_permission:read
Create/update recordsobject_configuration:read + record_permission:read-write
List entriesobject_configuration:read + record_permission:read + list_entry:read
Create/update entriesAbove + list_entry:read-write
Create notesnote:read-write + object_configuration:read + record_permission:read
List taskstask:read + object_configuration:read + record_permission:read + user_management:read
Manage webhookswebhook:read-write

Fix: Edit token in Settings > Developers > Access tokens, add missing scope, save. No need to regenerate.

404 Not Found -- not_found

{ "status_code": 404, "type": "not_found_error", "code": "not_found", "message": "..." }
CauseFix
Wrong object slugVerify with GET /v2/objects -- use api_slug field
Invalid record_idRecord may have been deleted or merged
Wrong list slugVerify with GET /v2/lists
Typo in endpoint pathCheck path starts with /v2/

409 Conflict -- conflict

Occurs 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" }],
    },
  },
});

422 Unprocessable Entity -- validation_error

Message patternCauseFix
Invalid email addressMalformed email stringValidate email format before sending
Invalid phone numberNot E.164 formatPrefix with country code: +14155551234
Unknown attributeAttribute slug does not existList attributes first
Invalid record referencetarget_record_id doesn't existVerify record exists first

429 Too Many Requests -- 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.

500+ Server Error

Rare, but Attio may reduce rate limits during incidents. Always implement retry for 5xx.

Check: status.attio.com

Quick Diagnostic Script

#!/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"

Error Handling Pattern

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;
  }
}

Resources

Next Steps

For evidence collection, see attio-debug-bundle. For retry patterns, see attio-rate-limits.

Keep looking

Skills are one crate of 328,083. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.