worker_exhausted
HTTP 500 · code: "worker_exhausted" · type: https://docs.formfeed.dev/errors/worker-exhausted
Something failed on Formfeed's side, and it is not a problem of your request. It comes in two ways:
- An async render ran out of attempts. The queue retries a render that fails on Formfeed's side (a timeout, a busy service, an unexpected failure) two more times, 5 and then 10 seconds later. When the third attempt fails too, the render fails with this code, and
detail(messagein the render'serror) keeps what the last attempt said. The render'serroralso hasattempts. - The API met an unexpected error before a render existed, for example when the database did not answer or the brand kit could not be read.
detailthen reads Unexpected error.
A failed render costs nothing.
Example
GET /v1/renders/{id}/result of an async render that timed out three times:
{
"type": "https://docs.formfeed.dev/errors/worker-exhausted",
"title": "Render retries exhausted",
"status": 500,
"detail": "Render exceeded 30000 ms",
"code": "worker_exhausted",
"location": null,
"render_id": "rnd_7da09ab6cd9946b798c187c2a9350852",
"request_id": "req_4b7c1e9a2f3d4c5b8a6e7f9012"
}
The same render in GET /v1/renders/{id} and the render.failed webhook:
"error": { "code": "worker_exhausted", "message": "Render exceeded 30000 ms", "attempts": 3 }
Common causes
- A render that times out every time, for example on a slow image server: the last message is Render exceeded 30000 ms. That is a problem of the template or its assets more than of Formfeed; see
render_timeout. - The office converter or the conformance service was unavailable for all three attempts.
- An infrastructure problem: a crashed browser, a storage error.
- An unexpected error in the API.
How to fix it
- Read
detail: when it names a timeout, fix it asrender_timeoutexplains; a retry will not help. - Otherwise retry the request later.
- If it keeps happening, check status.formfeed.dev and send the
request_id(and therender_id, if there is one) to support@formfeed.dev.
Retry?
Yes, with growing pauses (for example after 5, 30 and 120 seconds). For an answer of 500 to your request, use the same Idempotency-Key: such answers are not stored under the key, so each retry really runs. For an async render that failed later, send the request with a new Idempotency-Key: the first answer to the old key, the 202 with the failed render, is stored for 24 hours and would come back. This response has no Retry-After header, and the SDKs do not retry it by themselves.