{"record":{"id":"0216376901734547","repo":"odysseus-dev/odysseus","slug":"box-must-be-x1-y1-x2-y2","errorCode":null,"errorMessage":"Box must be [x1, y1, x2, y2]","messagePattern":"Box must be \\[x1, y1, x2, y2\\]","errorType":"http","errorClass":"HTTPException","httpStatus":400,"severity":"warning","filePath":"routes/gallery/gallery_routes.py","lineNumber":1880,"sourceCode":"        processor = backend[\"processor\"]\n        model = backend[\"model\"]\n        device = backend[\"device\"]\n\n        kwargs: Dict[str, Any] = {\"return_tensors\": \"pt\"}\n        input_points = []\n        if points:\n            input_labels = []\n            for p in points:\n                try:\n                    input_points.append([float(p[\"x\"]), float(p[\"y\"])])\n                    input_labels.append(int(p.get(\"label\", 1)))\n                except Exception as exc:\n                    raise HTTPException(400, \"Invalid point format\") from exc\n            kwargs[\"input_points\"] = [input_points]\n            kwargs[\"input_labels\"] = [input_labels]\n        if box:\n            if not isinstance(box, list) or len(box) != 4:\n                raise HTTPException(400, \"Box must be [x1, y1, x2, y2]\")\n            try:\n                kwargs[\"input_boxes\"] = [[[float(v) for v in box]]]\n            except Exception as exc:\n                raise HTTPException(400, \"Invalid box format\") from exc\n\n        try:\n            inputs = processor(image, **kwargs)\n            model_inputs = _model_inputs_to_device(inputs, device, torch)\n            with torch.no_grad():\n                outputs = model(**model_inputs)\n            masks = processor.image_processor.post_process_masks(\n                outputs.pred_masks.detach().cpu(),\n                inputs[\"original_sizes\"].detach().cpu(),\n                inputs[\"reshaped_input_sizes\"].detach().cpu(),\n            )\n            mask_tensor = masks[0]\n            while getattr(mask_tensor, \"ndim\", 0) > 3:\n                mask_tensor = mask_tensor[0]","sourceCodeStart":1862,"sourceCodeEnd":1898,"githubUrl":"https://github.com/odysseus-dev/odysseus/blob/f9235ebbf13f693a6fd29ce70b097f6ec83705bf/routes/gallery/gallery_routes.py#L1862-L1898","documentation":"HTTP 400 from SAM mask box validation: the 'box' field must be a JSON list of exactly 4 numbers ([x1, y1, x2, y2]). A tuple-like object, a dict, a string, or a list of length != 4 fails the isinstance/len check before any float conversion is attempted.","triggerScenarios":"POST with box={\"x1\":0,...} (dict), box=[0,0,100] (3 elements), box=[0,0,100,200,5] (5 elements), or box=\"0,0,100,200\" (string).","commonSituations":"Client stores the box as an object; box assembled from a bbox that sometimes returns None or an extra confidence element (e.g. [x1,y1,x2,y2,score]); grounding pipeline appending a score as a 5th value.","solutions":["Send box as a flat 4-element numeric array: [x1, y1, x2, y2]","Slice detection outputs to the first 4 elements before sending: box = det.box[:4]","Verify no wrapper nesting like box=[[0,0,100,200]] — the server adds its own nesting for the processor"],"exampleFix":"# before\nbox = {\"x1\": 10, \"y1\": 20, \"x2\": 110, \"y2\": 220}\n\n# after\nbox = [10, 20, 110, 220]","handlingStrategy":"validation","validationCode":"def is_valid_box(box) -> bool:\n    return isinstance(box, list) and len(box) == 4 and all(\n        isinstance(v, (int, float)) and not isinstance(v, bool) for v in box\n    )\n\nassert is_valid_box(body.get(\"box\")), 'box must be [x1, y1, x2, y2]'","typeGuard":"function isBox4(v: unknown): v is [number, number, number, number] {\n  return Array.isArray(v) && v.length === 4 && v.every(n => typeof n === 'number' && Number.isFinite(n));\n}","tryCatchPattern":null,"preventionTips":["Slice detector outputs to exactly four elements (drop any 5th confidence value) before sending","Keep boxes as flat numeric arrays end-to-end; never store them as objects in client state","Remember the server adds the nesting the SAM processor needs — send one flat array, not [[...]]"],"tags":["http-400","validation","bounding-box","sam","request-body"],"backgroundTag":null,"analyzedSha":"f9235ebbf13f693a6fd29ce70b097f6ec83705bf","analyzedAt":"2026-08-14T21:47:48.359Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}