odysseus-dev/odysseus · warning · HTTPException
Provide at least one point, box, or object text
Error message
Provide at least one point, box, or object text
What it means
HTTP 400 from the SAM smart-mask endpoint when the request contains no points, no box, and no text query to ground. The endpoint first tries to convert free text into a box via _ground_text_to_box; only if that also yields nothing does it reject the request. It is a pure request-shape validation error.
Source
Thrown at routes/gallery/gallery_routes.py:1858
This endpoint intentionally does not inspect edit prompts. It only
turns explicit visual selection hints into a binary mask that the
editor can reuse for wand/layer-mask/inpaint workflows.
"""
require_privilege(request, "can_generate_images")
body = await request.json()
image = _b64_to_pil_image(body.get("image") or "", mode="RGB")
points = body.get("points") or []
box = body.get("box")
text = (body.get("text") or body.get("query") or "").strip()
grounded = None
if not points and not box and text:
grounded = _ground_text_to_box(image, text)
box = grounded["box"]
if not points and not box:
raise HTTPException(400, "Provide at least one point, box, or object text")
backend = _load_sam_backend()
torch = backend["torch"]
processor = backend["processor"]
model = backend["model"]
device = backend["device"]
kwargs: Dict[str, Any] = {"return_tensors": "pt"}
input_points = []
if points:
input_labels = []
for p in points:
try:
input_points.append([float(p["x"]), float(p["y"])])
input_labels.append(int(p.get("label", 1)))
except Exception as exc:
raise HTTPException(400, "Invalid point format") from exc
kwargs["input_points"] = [input_points]View on GitHub (pinned to f9235ebbf1)
Solutions
- Include at least one of: points=[{"x":..,"y":..,"label":1}], box=[x1,y1,x2,y2], or text="a red cup"
- If using text, verify the text is a concrete object description that the grounding model can localize
- Check the client sends the fields under the exact keys 'points', 'box', 'text' (or 'query')
Example fix
# before
requests.post(url, json={"image": b64}) # 400
# after
requests.post(url, json={"image": b64, "points": [{"x": 120, "y": 80, "label": 1}]}) Defensive patterns
Strategy: validation
Validate before calling
def has_mask_prompt(body: dict) -> bool:
return bool(
body.get("points")
or body.get("box")
or (body.get("text") or body.get("query") or "").strip()
)
if not has_mask_prompt(body):
raise ValueError("pick a point, draw a box, or type an object name first") Type guard
function isMaskRequest(o: unknown): o is { image: string } & (
| { points: { x: number; y: number; label?: number }[] }
| { box: [number, number, number, number] }
| { text: string }
) {
if (typeof (o as any).image !== 'string' || !(o as any).image) return false;
const p = (o as any).points, b = (o as any).box, t = ((o as any).text ?? (o as any).query ?? '').toString().trim();
return Boolean((Array.isArray(p) && p.length) || (Array.isArray(b) && b.length === 4) || t);
} Prevention
- Disable the mask-submit button until the user has clicked a point, drawn a box, or typed a query
- Mirror the server's falsy-collapse semantics: empty arrays and blank strings count as 'not provided'
- When relying on text grounding, tell users to name concrete objects ('the red mug') since failed grounding degrades to this 400
When it happens
Trigger: POST to the SAM mask route with {"image": "..."} only; or with text that fails grounding (returns no box); or with points/box keys present but empty lists/None (body.get('points') or [] collapses falsy values to empty).
Common situations: Frontend sends the mask request before the user clicks a point; text query typo so grounding finds no object; box sent as empty array; JSON field name mismatch (e.g. 'prompt' instead of 'text'/'query').
Related errors
- Box must be [x1, y1, x2, y2]
- No documents specified
- Invalid point format
- Invalid box format
- content is required
AI-assisted analysis of odysseus-dev/odysseus@f9235ebbf1 (2026-08-14).
Data as JSON: /api/errors/fdbd74e2def47d12.
Report an issue: GitHub.