Job refusals
What happens when a job:<id> run or a fallback route can't pick or reach a provider, the result.code values, and the route.skipped codes behind them.
Send endpointId: "job:<job id>" to run (REST, MCP or looot run) in place of a specific
endpoint id, and looot picks the first provider of that job, in prefer order, that can run now
and accepts your input. See Jobs and Fallback. When no
provider can be picked or reached, the run fails with error.code: "validation_error" and a
result.code naming the specific reason, one of the five below.
unknown_job
result.code: "unknown_job". The job:<id> you sent isn’t a job looot knows, and no endpoint is
filed under it either. The message suggests up to 3 close job ids. Retryable: no. Fix: use a
suggested id, or take the job.id/capability value from a search row (search_catalog,
GET /v1/catalog/search, looot search). Don’t guess the id. See search.
no_supply_for_job
result.code: "no_supply_for_job". The job exists in looot’s vocabulary, but no endpoint in the
catalog does it. The same code appears as a warning on search_catalog and discover with empty
results, before you ever try to run it. Retryable: no. Fix: search again in other words, pick a
different job, or ask for it with the capability_request tool. See capability_request.
needs_input
result.code: "needs_input". Every provider of the job was reachable, but none of their input
schemas accepted the input you sent. result.needs lists each provider id and the field names it
needs. Retryable: no. Fix: add one of the named fields (the search answer’s jobInputs names the
same fields with descriptions) and send a new idempotencyKey. See Job inputs.
no_runnable_provider
result.code: "no_runnable_provider". The job exists and its providers’ schemas would accept the
input, but none of them can run for this workspace right now (no usable credential, drained, or
unpriced). Retryable: no. Fix: connect a key for one of the listed providers, or pick another job. See Bring your own provider key.
invalid_input
result.code: "invalid_input". A value in a shared input field is malformed before it ever
reaches a provider: an email with no @, a url with no http:///https://, a domain that
isn’t a bare domain name, or a phone with under 7 digits. Charged $0. Retryable: no. Fix: correct
the value and send a new idempotencyKey; the same key replays the same refusal. See Job inputs.
When fallback runs but calls nothing
A run with fallback set can also fail with route_capped or route_no_fit on its error
object (these are documented in Run errors, since they apply to any
fallback route, a job: run or not). Both mean no provider was ever called, so the run charges
$0.
route_capped
Every candidate’s price was above fallback.maxCostUsd. Retryable: no. Fix: raise
fallback.maxCostUsd, or change the input; route.skipped says why each provider was skipped. See Cost cap.
route_no_fit
Nothing ran for any other reason (bad input, short balance, missing credential, a route policy).
Retryable: no. Fix: when every skip is one you can change (see route.skipped below), change the
input and retry; otherwise no provider for this job can run for this request right now, so try
another endpoint or report it. See Fallback.
route.skipped codes
route.skipped[] (on a fallback run) and the skipped list a job: run’s requestedJob object
carries name why each candidate that was not run got passed over: {endpointId, providerId, code, reason}.
| Code | Meaning |
|---|---|
excluded |
Named in fallback.exclude. |
unavailable |
Cannot run for this workspace now (disabled, drained, no usable credential). |
unpriced |
No price is published for it. |
not_idempotent |
The endpoint may change something, so fallback never tries it automatically. |
blocked_by_policy |
The workspace’s route policy refuses this candidate. |
input_invalid |
Your input doesn’t fit this provider’s schema. |
needs_identity |
This provider needs a field the input doesn’t have (the field is named in reason). |
no_credential |
No usable credential for this provider. |
over_cost_cap |
This candidate’s price is above fallback.maxCostUsd. |
insufficient_balance |
The workspace balance can’t cover this candidate’s price. |
not_on_this_path |
Left out on a synchronous fixture run; a live gateway call would try it. |
max_attempts |
fallback.maxAttempts was already reached. |
fallback_disabled |
Fallback was turned off after the run was queued. |
error_bound |
The route already hit its limit of 2 error-class attempts. |
provider_already_tried |
This provider already had one attempt earlier in the same route. |
stopped |
The walk already stopped (a hit, a weak hit, or stopAtFirstMiss after a miss). |
excluded, input_invalid, needs_identity, over_cost_cap and insufficient_balance are
things you can change on the next request. The rest describe a candidate that could never have run
on this route.