pbakaus/impeccable · error
generate-image: API error {}: {}
Error message
generate-image: API error {}: {}
What it means
The OpenAI image API returned an HTTP status outside 200..299. generate-image prints the status plus the first 300 characters of the response body and exits 1. This surfaces API-side rejections such as bad requests, authentication failures, or rate limits.
Source
Thrown at crates/context/src/generate_image.rs:363
.post("https://api.openai.com/v1/images/generations")
.set("Authorization", &format!("Bearer {}", key))
.set("content-type", "application/json")
.send_string(&serde_json::to_string(&Value::Object(m)).unwrap())
};
let (status, text) = match response {
Ok(r) => {
let st = r.status();
(st, r.into_string().unwrap_or_default())
}
Err(ureq::Error::Status(code, r)) => (code, r.into_string().unwrap_or_default()),
Err(e) => {
io.err(&format!("TypeError: fetch failed: {}\n", e));
return 1;
}
};
if !(200..300).contains(&status) {
let snippet: String = text.chars().take(300).collect();
io.err(&format!("generate-image: API error {}: {}\n", status, snippet));
return 1;
}
let json: Value = serde_json::from_str(&text).unwrap_or(Value::Null);
let b64 = json.get("data").and_then(|d| d.get(0)).and_then(|d| d.get("b64_json")).and_then(|b| b.as_str()).filter(|s| !s.is_empty());
let Some(b64) = b64 else {
io.err("generate-image: no image in response\n");
return 1;
};
let bytes = base64_decode(b64);
let _ = std::fs::write(abs(&out), bytes);
// best-effort embed + sidecar
// JS-PARITY: generate-image.mjs#676 reports whether the embed actually
// succeeded. The install-path-with-spaces half of #676 is a JS-only
// subprocess concern (fileURLToPath vs URL.pathname); the engine embeds
// in-process, so only the success tracking and message carry over here.
let embedded;
{
let mut sub_io = Io::captured("", io.cwd.clone(), io.env.clone()).0;View on GitHub (pinned to 2bc2879276)
Solutions
- Read the status and body snippet in the message: 401 → fix the API key; 429 → wait/retry with backoff; 400 → correct size/quality/ref parameters.
- Verify OPENAI_API_KEY is valid and has billing/quota enabled for the org.
- Reduce or validate inputs (smaller size, supported quality value, fewer/smaller reference images) and retry.
- Check the OpenAI status page for ongoing incidents if you see 5xx.
- Implement retry with exponential backoff for 429/5xx responses in any wrapper scripts.
Example fix
// before impeccable generate-image --size 9999x9999 --prompt "..." --out o.png // generate-image: API error 400: ... // after impeccable generate-image --size 1536x1024 --prompt "..." --out o.png
Defensive patterns
Strategy: retry
Validate before calling
// preflight the key and known-good parameters
if (!process.env.OPENAI_API_KEY?.startsWith("sk-")) throw new Error("invalid OPENAI_API_KEY");
const ALLOWED_SIZES = ["1024x1024", "1536x1024", "1024x1536"];
if (!ALLOWED_SIZES.includes(size)) throw new Error(`unsupported size: ${size}`); Try / catch
const r = spawnSync("impeccable", ["generate-image", ...], { encoding: "utf8" });
if (r.status !== 0) {
const m = r.stderr.match(/API error (\d+)/);
if (m && (m[1] === "429" || m[1].startsWith("5"))) {
await backoffAndRetry();
} else if (m && m[1] === "401") {
throw new Error("OPENAI_API_KEY rejected — rotate/fix the key");
} else throw new Error(r.stderr);
} Prevention
- Map HTTP status to action: 401 fix key, 400 fix params, 429 backoff, 5xx retry/status page.
- Keep request parameters (size, quality) within the model's supported values.
- Monitor org billing/quota before large generation batches.
- Retry 429/5xx with exponential backoff and jitter.
When it happens
Trigger: POST to the images endpoint returns 4xx/5xx: 401 for an invalid/revoked OPENAI_API_KEY, 400 for an invalid size/quality/parameter combination, 429 for rate limiting or quota exhaustion, 5xx for OpenAI outages.
Common situations: Expired or rotated API keys; requesting a size not supported by the model; free-tier quota exhausted; org billing issue; transient OpenAI incidents; sending reference images that are too large.
Understand the failure class
Background: "API error: {status}" and "HTTP 401/403/404/429/5xx" errors: non-2xx HTTP responses explained — this error's family across 27 libraries.
Related errors
- generate-image: no image in response
- Status failed: ${res.status} ${res.statusText}
- Poll failed: ${res.status} ${res.statusText}
- errBody.error || ('HTTP ' + res.status)
- HTTP ${res.status}
AI-assisted analysis of pbakaus/impeccable@2bc2879276 (2026-09-08).
Data as JSON: /api/errors/0f101ecfe31fa826.
Report an issue: GitHub.