roboflow/supervision · error · ValueError
Expected string to end in location tags, but got {result}
Error message
Expected string to end in location tags, but got {result} What it means
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.
Source
Thrown at src/supervision/detection/vlm.py:596
return xyxy, None, masks, None
if task == "<OPEN_VOCABULARY_DETECTION>":
xyxy = np.array(result["bboxes"], dtype=np.float32)
labels = np.array(result["bboxes_labels"])
# Also has "polygons" and "polygons_labels", but they don't seem to be used
return xyxy, labels, None, None
if task in ["<REGION_TO_CATEGORY>", "<REGION_TO_DESCRIPTION>"]:
if not isinstance(result, str):
raise ValueError(f"Expected string as {task} result, got {type(result)}")
if result == "No object detected.":
return np.empty((0, 4), dtype=np.float32), np.array([]), None, None
pattern = re.compile(r"<loc_(\d+)><loc_(\d+)><loc_(\d+)><loc_(\d+)>")
match = pattern.search(result)
if match is None:
raise ValueError(
f"Expected string to end in location tags, but got {result}"
)
w, h = _validate_resolution(resolution_wh)
xyxy = np.array([match.groups()], dtype=np.float32)
xyxy *= np.array([w, h, w, h]) / 1000
result_string = result[: match.start()]
labels = np.array([result_string])
return xyxy, labels, None, None
raise RuntimeError(f"Unimplemented task: {task}")
def _recover_gemini_json_objects(text: str) -> list[Any]:
"""
Salvage individual JSON objects from a malformed Gemini JSON array.
Scans for balanced `{...}` spans and parses each independently, keeping theView on GitHub (pinned to 7f254d9784)
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.
Example fix
# before text = processor.decode(generated_ids[0], skip_special_tokens=True) detections = sv.Detections.from_florence_2(result=text, task="<REGION_TO_CATEGORY>") # after text = processor.decode(generated_ids[0], skip_special_tokens=False) detections = sv.Detections.from_florence_2(result=text, task="<REGION_TO_CATEGORY>")
Defensive patterns
Strategy: validation
Validate before calling
import re
LOC_TAG = re.compile(r"<loc_(\d+)><loc_(\d+)><loc_(\d+)><loc_(\d+)>")
if not LOC_TAG.search(text):
logger.warning("No loc tags in model output; skipping") Type guard
def has_loc_tags(text: str) -> bool:
return re.search(r"<loc_(\d+)><loc_(\d+)><loc_(\d+)><loc_(\d+)>", text) is not None Try / catch
try:
detections = sv.Detections.from_florence_2(result=text, task="<REGION_TO_CATEGORY>")
except ValueError:
detections = sv.Detections.empty() # caption without grounding Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
- Invalid VLM result type: {type(result)}. Must be dict.
- Expected string as {task} result, got {type(result)}
- Failed to parse XML root from {annotation_path}
- Unsupported VLM value: {vlm}.
- Invalid type for 'lmm': {type(lmm)}. Must be LMM or str.
AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15).
Data as JSON: /api/errors/cc477ae57c1d3ab2.
Report an issue: GitHub.