windmill-labs/windmill · error · Error
inline_checkpoint API ${resp.status}
Error message
inline_checkpoint API ${resp.status} What it means
The client's inline_checkpoint integration posts checkpoint data to the Windmill API and throws this error when the HTTP response status is not OK (typescript-client/client.ts:2013). The status code is interpolated so you can see whether it was a 4xx (bad request, auth) or 5xx (server-side failure). A failed POST means the checkpoint record could not be stored, breaking resume/replay consistency.
Source
Thrown at typescript-client/client.ts:2013
const body = payload;
const chainTail = this._inlineChain.then(async () => {
const ctrl = new AbortController();
const t = setTimeout(() => ctrl.abort(), 10_000);
try {
const resp = await fetch(
`${OpenAPI.BASE}/w/${workspace}/jobs/wac/inline_checkpoint/${jobId}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${OpenAPI.TOKEN}`,
},
body,
signal: ctrl.signal,
},
);
if (!resp.ok) {
throw new Error(`inline_checkpoint API ${resp.status}`);
}
if (!errored) return undefined;
// The backend normalizes the failure before storing it, and hands
// back what it stored. Throwing from that, not from the marker posted
// above, is what makes this round and every replay read the same
// record even if the two sides ever disagree about how to build one.
//
// A backend predating the echo answers without a JSON body; the
// caller then falls back to the round trip of what it posted. A JSON
// body we cannot read is different: the normalized record may already
// be committed and we do not know what it says, so let this reject
// and take the suspend path, where the next round reads whatever the
// backend actually stored.
if (!(resp.headers.get("content-type") ?? "").includes("json")) {
return undefined;
}
return (await resp.json())?.failure;
} finally {View on GitHub (pinned to e474e8803c)
Solutions
- Read the interpolated status: 401/403 → refresh credentials; 404 → check server/client version match; 5xx → inspect backend logs.
- Retry transient 502/503/504 responses with backoff.
- Reduce the checkpoint payload size if you see 413.
- Upgrade the Windmill server to a version matching the TypeScript client.
Example fix
// before
await checkpoint(myHugeState); // 413 if state is huge
// after
try {
await checkpoint({ summary: summarize(myHugeState) }); // smaller body
} catch (e) {
if (/inline_checkpoint API 5\d\d/.test(String(e))) {
await sleep(1000);
await checkpoint({ summary: summarize(myHugeState) }); // retry transient
} else throw e;
} Defensive patterns
Strategy: retry
Validate before calling
function isRetryableCheckpointError(e: unknown): boolean {
const m = /inline_checkpoint API (\d{3})/.exec(String(e));
return !!m && Number(m[1]) >= 500;
} Try / catch
try {
await checkpoint(state);
} catch (e) {
if (/inline_checkpoint API (502|503|504)/.test(String(e))) {
await sleep(1000);
return await checkpoint(state); // one retry for transient failures
}
throw e; // 401/403/404/413 need a fix, not a retry
} Prevention
- Match client and server versions so the inline_checkpoint route exists.
- Keep checkpoint payloads small to avoid 413.
- Refresh long-lived tokens before long runs.
- Retry 5xx with backoff; treat 4xx as a code/config bug.
When it happens
Trigger: Calling a checkpoint wrapper when the inline_checkpoint endpoint returns non-2xx — 401/403 from expired or missing credentials, 404 because the route/job does not exist, 413 from an oversized payload, or 500 from a backend error.
Common situations: Token expired mid-run; calling checkpoints in a context where the endpoint is unavailable; posting checkpoint bodies above server limits; server/client version mismatch (older server lacking inline_checkpoint route).
Understand the failure class
Background: 'Something went wrong' / 'Request failed (500)' / 'HTTP error! status: 404' — what failed HTTP requests actually mean and how to find the real cause — this error's family across 28 libraries.
Related errors
- GET ${path} -> ${resp.status}
- ${text}
- HTTP ${response.status}
- ${req.status} - ${req.statusText} - ${await req.text()}
- Script creation for ${body.path} with parent ${body.parent_h
AI-assisted analysis of windmill-labs/windmill@e474e8803c (2026-09-03).
Data as JSON: /api/errors/16a793cef1f082b8.
Report an issue: GitHub.