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

  1. Include at least one of: points=[{"x":..,"y":..,"label":1}], box=[x1,y1,x2,y2], or text="a red cup"
  2. If using text, verify the text is a concrete object description that the grounding model can localize
  3. 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

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


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