odysseus-dev/odysseus · warning · Error

Found ${data.grounding.label || 'object'}, but SAM returned

Error message

Found ${data.grounding.label || 'object'}, but SAM returned an empty mask

What it means

Thrown when the mask endpoint succeeds and returns a mask but no bbox, meaning SAM produced an empty/zero-area segmentation. If grounding metadata is present the message names the detected label ('Found dog, but SAM returned an empty mask'); otherwise it is the bare 'SAM returned an empty mask'. This is a model-quality failure, not a transport error.

Source

Thrown at static/js/galleryEditor.js:2011

  }
}

async function _requestAndApplySamMask(layer, payload, mode, seedPoint, opts = {}) {
  const res = await fetch('/api/image/mask', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      signal: opts.signal,
      body: JSON.stringify({
        image: layer.canvas.toDataURL('image/png').split(',')[1],
        ...payload,
      }),
    });
  const data = await res.json().catch(() => ({}));
  if (!res.ok || !data.mask) {
    throw new Error(data.detail || data.error || `Mask failed (${res.status})`);
  }
  if (!data.bbox) {
    throw new Error(data.grounding ? `Found ${data.grounding.label || 'object'}, but SAM returned an empty mask` : 'SAM returned an empty mask');
  }

  const img = new Image();
  await new Promise((resolve, reject) => {
    img.onload = resolve;
    img.onerror = () => reject(new Error('Failed to decode mask'));
    img.src = 'data:image/png;base64,' + data.mask;
  });
  const mask = document.createElement('canvas');
  mask.width = layer.canvas.width;
  mask.height = layer.canvas.height;
  const mctx = mask.getContext('2d');
  mctx.drawImage(img, 0, 0, mask.width, mask.height);
  const maskData = mctx.getImageData(0, 0, mask.width, mask.height);
  const md = maskData.data;
  for (let i = 0; i < md.length; i += 4) {
    const alpha = md[i]; // server mask is white selected / black unselected
    md[i] = 255;

View on GitHub (pinned to f9235ebbf1)

Solutions

  1. Click again closer to the center of the target object.
  2. Try a box/rect selection mode instead of a single seed point.
  3. Zoom in and retry on a well-contrasted part of the target.
  4. If it always fails, verify the SAM checkpoint version matches what the server expects.
Defensive patterns

Strategy: validation

Validate before calling

if (!data.mask || !data.bbox || data.bbox.every(v => v === 0)) { throw new Error('SAM returned an empty mask — retry with a different click'); }

Try / catch

catch (e) { if (/empty mask/i.test(e.message)) { toast('Click closer to the center of the object and retry'); return; } throw e; }

Prevention

When it happens

Trigger: Clicking on a point/region where the grounding model detects a label but SAM cannot segment it at that pixel (low contrast, tiny object, ambiguous click); prompting on flat backgrounds like sky or walls; resolution mismatch between the source image SAM saw and the canvas.

Common situations: Users clicking imprecisely on object edges; photos with heavy motion blur or low contrast; a grounding hit on a coarse label ('object') with no real instance under the cursor.

Related errors


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