odysseus-dev/odysseus · error · Error
data.error
Error message
data.error
What it means
Thrown when POST /api/image/inpaint returns HTTP 200 but the JSON body carries an error field. This pattern means the backend chose to report a failure (typically an upstream AI provider error) inside a successful response instead of a non-2xx status.
Source
Thrown at static/js/editor/ai-inpaint.js:157
const baseSnap = document.createElement('canvas');
baseSnap.width = state.imgWidth;
baseSnap.height = state.imgHeight;
baseSnap.getContext('2d').drawImage(flatCanvas, 0, 0);
const res = await fetch('/api/image/inpaint', {
method: 'POST', credentials: 'same-origin',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify((() => {
const sel = getSelectedAIEndpoint('inpaint');
return { image: imageB64, mask: maskB64, prompt, width: state.imgWidth, height: state.imgHeight, strength, feather: 0, _endpoint: sel.endpoint, _model: sel.model };
})()),
});
if (!res.ok) {
let errDetail = res.statusText;
try { const errBody = await res.json(); errDetail = errBody.detail || errBody.error || errDetail; } catch {}
throw new Error(errDetail);
}
const data = await res.json();
if (data.error) throw new Error(data.error);
if (!data.image) throw new Error('No image returned from inpaint endpoint');
// Load result as a new layer and clip with the user-drawn mask
// so only the inpainted region is visible. Cache the
// unfeathered (AI image + hard mask) on the layer so the live
// Feather slider can re-derive the alpha on each input event
// without re-running the model.
const resultImg = new Image();
resultImg.onload = () => {
if (!state.editorOpen) return; // user closed mid-decode
try {
saveState('Inpaint result');
// OpenAI returns at one of its allowed sizes (1024²,
// 1024×1536, 1536×1024) which often differs from our
// canvas. Scale to canvas size with smoothing so the
// inpaint blends in regardless of source dims.
const shortPrompt = (prompt || '').trim().replace(/\s+/g, ' ').slice(0, 40);
const layerName = shortPrompt ? `Inpaint: ${shortPrompt}` : 'Inpaint Result';
const resultLayer = createLayer(layerName, state.imgWidth, state.imgHeight);View on GitHub (pinned to f9235ebbf1)
Solutions
- Read the data.error string — it is the upstream provider message and names the real cause
- Fix the configuration it points at (valid model name for the endpoint, quota, prompt wording)
- Retry after clearing the rate-limit window if the error mentions 429/quota
- If you own the backend, return proper 4xx/5xx statuses instead of 200-with-error so monitoring counts these
Defensive patterns
Strategy: validation
Validate before calling
const data = await res.json(); if (data.error) throw new Error(data.error);
Type guard
function isInpaintSuccess(d) { return typeof d === 'object' && d !== null && typeof d.image === 'string' && d.image.length > 0; } Try / catch
try { const data = await res.json(); if (data.error) throw new Error(data.error); if (!isInpaintSuccess(data)) throw new Error('No image returned from inpaint endpoint'); ... } catch (e) { uiModule.showToast('Inpaint failed: ' + e.message); } Prevention
- Always check both transport (!res.ok) and application (data.error) failure modes
- Validate provider config (key, model) before long-running inpaint calls
- Prefer backends that return real 4xx/5xx for provider failures so monitoring sees them
- Type-guard the success shape before touching data.image
When it happens
Trigger: The provider call inside the server fails after the request was accepted: invalid model name for the selected endpoint, provider quota exhausted, content policy rejection, or a provider timeout — the server wraps that as {error: '...'} with 200.
Common situations: Switching _model to one the key does not have access to; provider rate limits hit mid-session; NSFW filter triggering on the prompt/mask region; server code that catches upstream exceptions and returns data.error rather than raising HTTPException.
Related errors
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/cdcb0b7ea2f9b2f8.
Report an issue: GitHub.