SDK errors
The SDK surfaces metadata for exceptions. All errors inherit fromperceptron.errors.SDKError.
Error / err.code | Triggers | Suggested next step |
|---|---|---|
AuthError (auth) | Missing/invalid API key, revoked org access | Re-export PERCEPTRON_API_KEY, double-check PERCEPTRON_PROVIDER/BASE_URL, share the request_id. |
BadRequestError (bad_request) | Invalid payloads, malformed prompts, unsupported params | Inspect err.details["message"] / offending field; fix input before retrying. |
ExpectationError (expectation_failed) | Strict-mode validation (boxes missing anchors, malformed coordinates) | Keep prompts/images ordered, attach image= handles, validate coordinates with result.points_to_pixels(). |
AnchorError (anchor_missing, bounds_out_of_range) | Dedicated anchor violations exposed via strict mode | Add explicit anchors or clamp/rescale boxes; log err.details["code"]. |
RateLimitError (rate_limit) | 429 from API or provider | Read err.details["retry_after"], back off exponentially, log request_id. |
TimeoutError (timeout) | Client-side deadline exceeded | Increase config(timeout=...), trim uploads, consider stream=True. |
TransportError (transport) | Network failures (DNS, TLS, broken pipes) | Retry with jitter; if persistent, verify outbound firewall / proxy. |
ServerError (server_error) | 5xxs or malformed upstream responses | Retry automatically up to your policy; include request_id when contacting support. |
PerceiveResult.errors; flip strict=True when you want them raised immediately during prompting and pointing.
Retrying safely
Wrap SDK calls with targeted exception handling so transient faults (rate limits, network blips) never crash your job while still surfacing actionable diagnostic info.API error codes
API responses bubble up through the SDK as the error classes above. Use the table below to match symptoms (HTTP status, timeout, etc.) to the remediation you need in client code.401 Unauthorized
401 Unauthorized
403 Forbidden
403 Forbidden
Symptom: Key is valid but lacks scope.Fix: Rotate/regenerate the key in the dashboard and ensure the organization has access to the requested provider (
perceptron, fal, etc.).429 Rate limit
429 Rate limit
Symptom: Too many requests per minute.Fix: Batch requests and implement exponential backoff using the surfaced
retry_after seconds.400/422 Validation
400/422 Validation
Symptom: Immediate
BadRequestError, ExpectationError, or warnings in PerceiveResult.errors.Fix: Inspect err.details (provider message, offending field, request ID) or switch on strict=True to surface anchor issues early.500 Server error
500 Server error
Symptom: Transient backend issue.Fix: Retry with jitter and log
err.details.get("request_id") when opening support tickets.Timeout / connection reset
Timeout / connection reset
Symptom: Long-running uploads or unstable network.Fix: Resize oversized images (
<=1024px longest edge), prefer stream=True to receive incremental tokens, and reduce config(timeout=...) so hung connections fail fast.Decision trees with runnable repros
invalid_image (upload/source bytes)
- Meaning: the SDK could not decode the bytes you pointed it at before the request ever left your machine.
- Fix checklist:
- Make sure the path/bytes you pass into
caption()/detect()/ocr()is a real bitmap (PNG/JPEG/WebP). When dealing with streams, flush the handle before re-reading it. - Inspect
err.details['origin']to confirm which file triggered the failure anderr.details['request_id'](if the request made it to the API). - If the asset lives on disk, open it with Pillow or Preview to confirm it is not truncated; if it is an HTTP URL, download it locally and retry.
- Make sure the path/bytes you pass into
anchor_missing / bounds_out_of_range (strict pointing)
- Meaning: a
box()/point()/polygon()tag is missing an explicitimage=reference when multiple images exist, or the coordinates fall outside the detected width/height. - Fix checklist:
- When using
@perceive(..., strict=True)always pass the image node into every tag:box(..., image=image_node). In single-image prompts, ensure the image appears before any tags. - Use
result.points_to_pixels(width, height)to sanity-check coordinate math before switching to strict mode. - Log
err.details['code'](eitheranchor_missingorbounds_out_of_range) to branch your retry logic.
- When using