HTTP errors
| Status | Description | Retry? |
|---|---|---|
400 |
A problem with one of the request's inputs. The JSON response carries an error member with a human-readable explanation. |
No |
401 |
The API key is not valid. | No |
404 |
The referenced resource is not available. | No |
405 |
The endpoint was called with an unsupported HTTP method. | No |
429 |
Too many requests in a period, or an integration limit was reached. | Yes |
502 |
Runway is shedding load. | Yes |
503 |
Runway is shedding load. | Yes |
504 |
Runway is overloaded and could not satisfy the request. | Yes |
Retrying correctly#
When a status is retryable, use exponential backoff with jitter. Add a random delay of up to 50% to each retry interval — without it, every client that failed at the same moment retries at the same moment, and the recovering service is knocked over again.
async function withRetry(fn, maxAttempts = 5) {
for (let attempt = 0; attempt < maxAttempts; attempt++) {
try {
return await fn();
} catch (error) {
const retryable = [429, 502, 503, 504].includes(error.status);
if (!retryable || attempt === maxAttempts - 1) throw error;
const base = 1000 * 2 ** attempt;
const jitter = Math.random() * base * 0.5;
await new Promise((r) => setTimeout(r, base + jitter));
}
}
}Runway's SDKs handle retries automatically. The code above is for direct REST integrations; if you use the Node.js or Python SDK, you already have this behaviour.
Reading each code#
400 Bad Request almost always means an input violated a documented constraint — an oversized asset, an unsupported codec, a Content-Type of application/octet-stream, a malformed data URI, or an aspect ratio outside the model's window. The error member names the problem. Fix the input; never retry.
401 Unauthorized means the key is invalid, disabled or absent. Check that RUNWAYML_API_SECRET is set in the environment the code actually runs in.
404 Not Found on task retrieval usually means a mistyped ID. Note that a 404 from an idempotent delete is expected and harmless — exclude it from your error-rate alerting.
429 Too Many Requests means you hit your tier's daily generation cap or another integration limit. There is no requests-per-minute limit as long as you stay within your daily generation allowance — excess concurrent work is queued as THROTTLED rather than rejected. A persistent 429 therefore points at the daily cap, and the fix is tiering up rather than backing off harder.
502, 503, 504 are Runway-side. Retry with backoff; they resolve.
Errors versus task failures#
An HTTP error means the request failed. A task that is accepted (200) can still fail later during generation, reporting a failureCode instead. Those are documented separately in task failures — and the retry rules there are different, including one case where credits are not refunded.
Related#
- Task failures — failures after a task is accepted
- Go-live checklist — testing your failure handling
- Usage tiers — the limits behind most
429s
The go-live checklist covers the failure modes that actually appear in production.