Troubleshooting
Common errors, their causes, and how to fix them — plus debugging tools built into every Aira deployment.
Quick diagnostics
Before diving into specific errors, run these two checks:
# 1. Is the server healthy?
curl https://your-domain/api/v1/health
# 2. Is your API key valid?
curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer aira_live_..." \
https://your-domain/api/v1/health
# 200 = valid, 401 = invalid/expiredIf /health returns 200, the API server, database, and signing service are all operational. If it returns anything else, the issue is infrastructure — not your code.
Common errors
POLICY_DENIED (HTTP 403)
The action was blocked by one or more policy rules.
Symptoms:
{
"error": {
"code": "POLICY_DENIED",
"message": "Action blocked by policy: 'no-pii-in-prompts'",
"details": {
"policy_id": "pol_abc123",
"rule": "no-pii-in-prompts"
}
}
}Fix:
- Check which policies are active: go to Dashboard > Policies or call
GET /api/v1/policies. - Review the
details.policy_idto find the specific rule that fired. - Either adjust your action payload to comply with the policy, or update the policy rules if the block is unintended.
POLICY_DENIED is not an error — it means Aira is working correctly. The action was intentionally blocked because it violated a rule you (or your org admin) configured.
401 Unauthorized
Your API key is missing, expired, or invalid.
Common causes:
- The key was revoked or rotated in the dashboard.
- You are using a test key (
aira_test_...) against the production API, or vice versa. - The
Authorizationheader is malformed (must beBearer aira_live_...).
Fix:
- Go to Dashboard > API Keys and check the key status.
- If expired, generate a new key and update your environment variable.
- Verify the header format:
# Correct
curl -H "Authorization: Bearer aira_live_abc123..." ...
# Wrong — missing "Bearer" prefix
curl -H "Authorization: aira_live_abc123..." ...403 Forbidden
You are authenticated but lack permission for this action.
Common causes:
- Your API key belongs to a different organization than the resource you are accessing.
- Your role (viewer, member) does not have write access to the endpoint.
- The resource belongs to a different sub-product and your key is scoped.
Fix:
- Confirm your org ID matches the resource:
GET /api/v1/healthreturns your org context. - Check your role in Dashboard > Team.
- If using scoped keys, verify the key has access to the sub-product in question.
429 Too Many Requests
You have exceeded the rate limit for your plan.
Symptoms:
{
"error": {
"code": "RATE_LIMITED",
"message": "Rate limit exceeded. Retry after 2 seconds."
}
}Fix:
Implement exponential backoff. Both SDKs handle this automatically when configured:
# Python SDK — built-in retry with backoff
from aira import Aira
client = Aira(
api_key="aira_live_...",
)// TypeScript SDK — built-in retry with backoff
import { Aira } from "aira-sdk";
const aira = new Aira({
apiKey: "aira_live_...",
});If you are hitting limits consistently, check your plan quotas at Dashboard > Usage or contact support to upgrade.
model_error in cases
The AI model returned invalid or unparseable JSON when evaluating a case.
Common causes:
- A custom model endpoint is returning non-JSON responses.
- The model is returning JSON that does not match the expected schema.
- Network issues between Aira and the model provider.
Fix:
- Check the case detail in the dashboard — the raw model response is logged.
- If using a custom model endpoint, verify it returns valid JSON by testing directly:
curl -X POST https://your-model-endpoint/v1/chat/completions \
-H "Content-Type: application/json" \
-d '{"model":"your-model","messages":[{"role":"user","content":"test"}]}'- Verify the model endpoint is listed in Dashboard > Models and is reachable from Aira.
Webhook delivery failures
Aira retries failed webhook deliveries with exponential backoff (up to 5 attempts). If all retries fail, the webhook is marked as failed in the dashboard.
Common causes:
- Your endpoint is unreachable (DNS, firewall, or the server is down).
- Your endpoint does not return a 2xx status within 10 seconds.
- TLS certificate issues (expired cert, self-signed cert without configuration).
Fix:
- Check Dashboard > Webhooks for delivery logs and error messages.
- Test your endpoint manually:
curl -X POST https://your-webhook-url \
-H "Content-Type: application/json" \
-d '{"test": true}'- Ensure your endpoint responds with HTTP 200 within 10 seconds.
- For TLS issues, verify your certificate chain is complete and not expired.
- If developing locally, use a tunnel like ngrok to expose your endpoint:
ngrok http 8000
# Use the https://...ngrok.io URL as your webhook endpointWebhook payloads include a signature header (X-Aira-Signature). Always verify this signature to ensure the payload was sent by Aira. See the Webhook Verification guide.
Debugging tools
/health endpoint
Every Aira deployment exposes a health endpoint that returns server status, version, and component health:
curl https://your-domain/api/v1/health | python -m json.tool{
"status": "healthy",
"version": "1.4.0",
"components": {
"database": "healthy",
"signing": "healthy"
}
}Use this to confirm your deployment is running and which version is active.
Swagger UI
Every Aira deployment includes interactive API documentation at /docs. Open it in your browser to:
- Browse all available endpoints.
- Send test requests directly from the UI.
- Inspect request/response schemas.
https://your-domain/docsAudit log
Every action, policy change, and team membership change is recorded in the audit log. Use it to trace what happened and when:
curl -H "Authorization: Bearer aira_live_..." \
"https://your-domain/api/v1/audit-logs?limit=20"You can also browse the audit log in Dashboard > Audit Log.
Verifying a receipt
If you need to confirm a receipt is genuine and has not been tampered with:
from aira import Aira
client = Aira(api_key="aira_live_...")
result = client.verify_action(action_uuid="rec_abc123")
print(result.valid) # True if signature and data are intact
print(result.timestamp) # RFC 3161 timestamp
print(result.action_uuid) # The action this receipt coversimport { Aira } from "aira-sdk";
const aira = new Aira({ apiKey: "aira_live_..." });
const result = await client.verify("rec_abc123");
console.log(result.valid); // true if signature and data are intact
console.log(result.timestamp); // RFC 3161 timestamp
console.log(result.actionUuid); // The action this receipt coversStill stuck?
- Check the Error Handling guide for the full error code reference.
- Review the Performance page if you suspect latency issues.
- Contact support at support@airaproof.com with your
request_idfor fastest resolution.