odysseus-dev/odysseus · error · Error

statusText

Error message

statusText

What it means

Thrown when POST /api/image/inpaint (AI inpainting in the image editor) responds non-2xx. The code prefers a JSON body field detail or error and falls back to res.statusText — which is frequently empty under HTTP/2, leaving the user with a blank error.

Source

Thrown at static/js/editor/ai-inpaint.js:154

      const dilatedMask = dilateMask(mergedMask, padPx);
      const imageB64 = flatCanvas.toDataURL('image/png').split(',')[1];
      const maskB64 = dilatedMask.toDataURL('image/png').split(',')[1];
      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.

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Check the inpaint response body in the Network tab — the JSON detail usually names the upstream cause (missing key, provider 401, model name)
  2. Verify an AI endpoint/model is selected and configured for the inpaint tool (getSelectedAIEndpoint)
  3. Reduce image dimensions if the 413 body limit is the cause
  4. Include res.status in the fallback message so it is never blank

Example fix

// before
let errDetail = res.statusText;

// after
let errDetail = `HTTP ${res.status}`;
Defensive patterns

Strategy: try-catch

Validate before calling

const sel = getSelectedAIEndpoint('inpaint');
if (!sel.endpoint) { uiModule.showToast('Select an AI endpoint first'); return; }
if (!imageB64 || !maskB64) { uiModule.showToast('Draw a mask before inpainting'); return; }

Try / catch

if (!res.ok) { let errDetail = `HTTP ${res.status}`; try { const b = await res.json(); errDetail = b.detail || b.error || errDetail; } catch {} throw new Error(errDetail); }

Prevention

When it happens

Trigger: Running Inpaint with a mask and prompt: the upstream AI provider key is missing/invalid (usually 500 with detail), the request payload exceeds the server's body limit (413), the selected custom endpoint in getSelectedAIEndpoint('inpaint') is unreachable, or credentials expired (401).

Common situations: No AI provider API key configured on the server; user-selected custom endpoint URL wrong or rate-limited; very large canvas producing a multi-MB base64 payload rejected by a proxy; statusText empty so 'Inpaint failed: ' shows nothing useful.

Related errors


AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14). Data as JSON: /api/errors/42ca0b546d5c4e3a. Report an issue: GitHub.