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
- Click again closer to the center of the target object.
- Try a box/rect selection mode instead of a single seed point.
- Zoom in and retry on a well-contrasted part of the target.
- 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
- Validate bbox is non-degenerate before building the mask canvas
- Treat empty masks as retryable UX guidance, not hard failures
- Prefer box prompts over single seed points on low-contrast subjects
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
- data.detail || data.error || `Mask failed (${res.status})`
- Provide at least one point, box, or object text
- SAM mask failed: {exc}
- statusText
- data.error
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/eda8a57ece4b63d7.
Report an issue: GitHub.