Service errors
Apps call Clawnify’s built-in services (PDFs, screenshots, page reads, scheduled jobs, video, code runs, document comparisons) at services.clawnify.com, through @clawnify/services and @clawnify/queue. When a service says no, both packages throw an error carrying:
code: what went wrong, one of the codes below. Branch on this, never on the text.status: the HTTP status.message: the service’s explanation when it sent one, otherwise the code itself.
Calling a route without a package? The answer body is { "error": "<code>", "detail": "<explanation>" }, sometimes with extra fields.
What to show
Who can fix it decides what the app shows.
- The workspace owner (credits, plan, access). Show
message: it is written for a person and says where to go. If the person using the app may not be the owner, add “Ask the workspace owner.” - Whoever sent the request (a bad file, a page that isn’t public). Say in your own words what was wrong with what they sent.
messagehere is often technical or comes from a third party, so log it rather than show it. - Clawnify. Say something went wrong on Clawnify’s side and to try again. Background work retries later, with a growing delay.
- Nobody yet (still processing). Not an error: wait and ask again.
Work nobody is watching
A scheduled job, a nightly sync, a webhook handler: when one of these is refused, nobody is looking at the app. Never catch the error and carry on as if nothing happened. Keep the last refusal, show it where the owner looks (a banner on the app’s main page), and return it from the app’s status endpoint so an agent can read it too. An app that swallows a refusal stops working with nothing on screen saying why.
Included use and credits
Each plan includes a monthly amount of every service. Past it, the service keeps working and each call uses credits, so an app never stops because a monthly counter ran out. A call is refused only when the credits run out (insufficient_credits) or the workspace has no active plan (quota_exceeded). Settings → Usage shows what each service has used this month and, at the current pace, when the included amount runs out.
The owner can fix it
| Code | Status | Means | Where it’s fixed |
|---|---|---|---|
insufficient_credits | 402 | The month’s included use is spent and the credits can’t pay for more | Billing: add credits or change plan |
quota_exceeded | 403 | The workspace has no active plan | Billing |
scope_required | 403 | The workspace hasn’t been given access to this service | Ask Clawnify support |
invalid_token | 401 | The app’s Clawnify token is missing or was revoked | Redeploy the app, which gives it the workspace’s current token |
storage_full | 409 | The workspace holds as much video footage as it can | Delete footage it no longer needs |
Whoever sent the request can fix it
| Code | Status | Means |
|---|---|---|
invalid_request | 422 | A field is missing or malformed |
render_failed | 422 | The page or HTML couldn’t be rendered: not public, too slow, or broken |
capture_invalid | 422 | The capture plan doesn’t match the expected shape (problems lists why) |
capture_failed | 422 | The page walk failed partway |
edl_invalid | 422 | The video edit list is invalid (path points at the field) |
edit_failed | 422 | A video source couldn’t be fetched or processed |
exec_failed | 422 | The code, its files or its requirements were rejected before running |
redline_failed | 422 | The documents or the edits couldn’t be compared |
invalid_source | 422 | The video link is unreachable, private, or not a video |
import_failed | 422 | The video host refused the import |
too_long | 422 | The video is too long to analyse in one pass |
presign_failed | 422 | The file isn’t a staged upload, or it expired |
forbidden_source | 403 | The file belongs to another workspace |
too_large | 413 | The upload is over 500 MB |
unsupported_media_type | 415 | The upload isn’t a media file |
length_required | 411 | The upload has no length |
empty_body | 400 | The upload is empty |
not_found | 404 | No such job, file or video, or it belongs to another workspace |
Nobody needs to fix it yet
| Code | Status | Means |
|---|---|---|
not_ready | 409 | The video is still processing. Ask again shortly |
source_not_ready | 409 | Prepare the video first, then ask again |
conflict | 409 | The scheduled job already ran or was cancelled. Treat it as done |
Clawnify’s side
internal_error (500), upload_unavailable (502) and not_configured (503): show a short apology, and retry background work later. Nothing the owner or the user does changes them.
Failures that answer 200
Some failures are a normal answer with a failure inside it, so check for them:
- Jobs you poll (video render, video edit, video analysis, footage re-encode) come back with a
statusoffailedand adetailsaying why. - Code runs answer
ok: falsewith the exit code,stdoutandstderr. - Document comparisons mark each edit they couldn’t place:
not_found,ambiguousorinvalid. - Scheduled jobs you look up can be
failed, withlast_errorholding what your own app answered when the queue called it.