nexu-io/open-design · error · Error
${tag} ${resp.status}: ${truncate(text, 240)}
Error message
${tag} ${resp.status}: ${truncate(text, 240)} What it means
Thrown by renderOpenAIImage after the images/generations fetch returns a non-2xx status. The tag is 'azure-openai' when detectAzureEndpoint flagged the base URL, otherwise 'openai'. The message includes resp.status and the first 240 chars of the response body so quota/auth/model errors are visible. This is the catch-all upstream HTTP failure for the OpenAI image path.
Source
Thrown at apps/daemon/src/media/index.ts:953
// Azure's canonical auth header. Some deployments accept Bearer
// (the curl example we tested against does) but api-key is what
// their docs document, so send both. OpenAI ignores unknown
// headers, so this is harmless on the standard endpoint too.
headers['api-key'] = credentials.apiKey;
}
const resp = await fetch(url, withMediaRequestInit(ctx, {
method: 'POST',
headers,
body: JSON.stringify(body),
dispatcher: ctx.requestInit.dispatcher
?? openAIImageDispatcher as unknown as NonNullable<RequestInit['dispatcher']>,
signal: AbortSignal.timeout(Math.max(OPENAI_IMAGE_HEADERS_TIMEOUT_MS, OPENAI_IMAGE_BODY_TIMEOUT_MS)),
}));
const text = await resp.text();
if (!resp.ok) {
const tag = azure ? 'azure-openai' : 'openai';
throw new Error(`${tag} ${resp.status}: ${truncate(text, 240)}`);
}
let data: any;
try {
data = JSON.parse(text);
} catch {
throw new Error(`openai non-JSON response: ${truncate(text, 200)}`);
}
const entry = data && Array.isArray(data.data) ? data.data[0] : null;
if (!entry) throw new Error('openai response had no data[0]');
let bytes;
if (entry.b64_json) {
bytes = Buffer.from(entry.b64_json, 'base64');
} else if (entry.url) {
const imgResp = await fetch(entry.url, withMediaRequestInit(ctx));
if (!imgResp.ok) throw new Error(`openai image fetch ${imgResp.status}`);
const arr = await imgResp.arrayBuffer();
bytes = Buffer.from(arr);
} else {View on GitHub (pinned to 5be4028344)
Solutions
- Read the embedded status and body snippet: 401/403 -> rotate/regenerate the key; 429 -> slow down or upgrade plan; 404 -> verify model id and Azure deployment name.
- Confirm credentials.baseUrl is correct (omit it for public OpenAI; set the full Azure deployment URL for Azure).
- Retry after the provider's Retry-Backoff for 429/5xx; the OpenAI image path does not auto-retry.
- Check the provider status page if 5xx persists.
Example fix
// before: wrong Azure deployment name -> 404 OD_OPENAI_BASE_URL=https://my-resource.openai.azure.com/openai/deployments/wrong-name // after OD_OPENAI_BASE_URL=https://my-resource.openai.azure.com/openai/deployments/correct-deployment
Defensive patterns
Strategy: retry
Validate before calling
function classifyOpenAIStatus(status: number): 'retry'|'fatal'|'config' {
if (status === 429 || status >= 500) return 'retry';
if (status === 401 || status === 403) return 'config';
return 'fatal';
} Try / catch
try {
return await renderOpenAIImage(ctx, credentials);
} catch (err) {
const m = err instanceof Error ? err.message : '';
const statusMatch = m.match(/(?:azure-openai|openai) (\d{3}):/);
const status = statusMatch ? Number(statusMatch[1]) : 0;
if (status === 429 || status >= 500) throw new RetryableError(m);
if (status === 401 || status === 403) throw new ConfigError('rotate OpenAI key');
throw err;
} Prevention
- Inspect the inlined status/body before retrying: only 429 and 5xx are worth retrying.
- Keep the OpenAI model id and Azure deployment name in sync to avoid 404s.
- Monitor quota in the OpenAI dashboard to pre-empt 402/429.
When it happens
Trigger: Invalid or revoked API key (401); exhausted quota or billing issue (402/429); requesting a model the deployment does not expose (404 on Azure); rate limiting (429); transient 5xx from OpenAI/Azure; wrong baseUrl pointing at a non-OpenAI host.
Common situations: Free-tier key hitting rate limits; Azure deployment name mismatch; baseUrl typo; shared key revoked; model deprecated by provider.
Related errors
- openai response had no data[0]
- ${providerTag} ${resp.status}: ${truncate(text, 240)}
- openai non-JSON response: ${truncate(text, 200)}
- openai image fetch ${imgResp.status}
- openai response had neither b64_json nor url
AI-assisted analysis of nexu-io/open-design@5be4028344 (2026-08-12).
Data as JSON: /api/errors/a3be5cf78d8091e8.
Report an issue: GitHub.