{"record":{"id":"cc477ae57c1d3ab2","repo":"roboflow/supervision","slug":"expected-string-to-end-in-location-tags-but-got","errorCode":null,"errorMessage":"Expected string to end in location tags, but got {result}","messagePattern":"Expected string to end in location tags, but got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/detection/vlm.py","lineNumber":596,"sourceCode":"        return xyxy, None, masks, None\n\n    if task == \"<OPEN_VOCABULARY_DETECTION>\":\n        xyxy = np.array(result[\"bboxes\"], dtype=np.float32)\n        labels = np.array(result[\"bboxes_labels\"])\n        # Also has \"polygons\" and \"polygons_labels\", but they don't seem to be used\n        return xyxy, labels, None, None\n\n    if task in [\"<REGION_TO_CATEGORY>\", \"<REGION_TO_DESCRIPTION>\"]:\n        if not isinstance(result, str):\n            raise ValueError(f\"Expected string as {task} result, got {type(result)}\")\n\n        if result == \"No object detected.\":\n            return np.empty((0, 4), dtype=np.float32), np.array([]), None, None\n\n        pattern = re.compile(r\"<loc_(\\d+)><loc_(\\d+)><loc_(\\d+)><loc_(\\d+)>\")\n        match = pattern.search(result)\n        if match is None:\n            raise ValueError(\n                f\"Expected string to end in location tags, but got {result}\"\n            )\n\n        w, h = _validate_resolution(resolution_wh)\n        xyxy = np.array([match.groups()], dtype=np.float32)\n        xyxy *= np.array([w, h, w, h]) / 1000\n        result_string = result[: match.start()]\n        labels = np.array([result_string])\n        return xyxy, labels, None, None\n\n    raise RuntimeError(f\"Unimplemented task: {task}\")\n\n\ndef _recover_gemini_json_objects(text: str) -> list[Any]:\n    \"\"\"\n    Salvage individual JSON objects from a malformed Gemini JSON array.\n\n    Scans for balanced `{...}` spans and parses each independently, keeping the","sourceCodeStart":578,"sourceCodeEnd":614,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/detection/vlm.py#L578-L614","documentation":"Raised while parsing Florence-2 '<REGION_TO_CATEGORY>'/'<REGION_TO_DESCRIPTION>' output when the returned string does not contain four consecutive '<loc_N>' tags. The regex r'<loc_(\\d+)><loc_(\\d+)><loc_(\\d+)><loc_(\\d+)>' searches the text for the region coordinates; if none are found, the location of the described object cannot be recovered and the error is raised.","triggerScenarios":"The model returns a plain caption without location tags (common when the task prompt was '<MORE_DETAILED_CAPTION>' or a region task on a non-grounded checkpoint), or the loc tags were stripped by a post-processing/decoding step (e.g. skip_special_tokens=True in processor.decode).","commonSituations":"Decoding Florence-2 output with skip_special_tokens=True so <loc_*> tokens are removed; using a captioning task but parsing with a region task; prompt/task token typos so the model falls back to captioning; fine-tuned checkpoints that emit a different tag format.","solutions":["Decode with skip_special_tokens=False so <loc_*> tags survive: processor.decode(output_ids[0], skip_special_tokens=False).","Verify the string passed in actually contains loc tags by printing it; strip only the task token, not the location tags.","Ensure the task string used for parsing matches the prompt used at inference.","Treat tag-less output as 'no detection' in your pipeline: check with re.search before calling, or catch ValueError and skip the frame."],"exampleFix":"# before\n text = processor.decode(generated_ids[0], skip_special_tokens=True)\n detections = sv.Detections.from_florence_2(result=text, task=\"<REGION_TO_CATEGORY>\")\n\n# after\n text = processor.decode(generated_ids[0], skip_special_tokens=False)\n detections = sv.Detections.from_florence_2(result=text, task=\"<REGION_TO_CATEGORY>\")","handlingStrategy":"validation","validationCode":"import re\n\nLOC_TAG = re.compile(r\"<loc_(\\d+)><loc_(\\d+)><loc_(\\d+)><loc_(\\d+)>\")\n\nif not LOC_TAG.search(text):\n    logger.warning(\"No loc tags in model output; skipping\")","typeGuard":"def has_loc_tags(text: str) -> bool:\n    return re.search(r\"<loc_(\\d+)><loc_(\\d+)><loc_(\\d+)><loc_(\\d+)>\", text) is not None","tryCatchPattern":"try:\n    detections = sv.Detections.from_florence_2(result=text, task=\"<REGION_TO_CATEGORY>\")\nexcept ValueError:\n    detections = sv.Detections.empty()  # caption without grounding","preventionTips":["Always decode Florence-2 output with skip_special_tokens=False.","Treat tag-less region output as 'no detection', matching the library's 'No object detected.' branch.","Add a smoke test asserting loc tags survive your decoding step."],"tags":["florence-2","vlm","parsing","loc-tags"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}