{"record":{"id":"b1d7c0326b5e0a85","repo":"roboflow/supervision","slug":"expected-string-as-task-result-got-type-result","errorCode":null,"errorMessage":"Expected string as {task} result, got {type(result)}","messagePattern":"Expected string as (.+?) result, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"src/supervision/detection/vlm.py","lineNumber":588,"sourceCode":"                masks_list.append(mask)\n                xyxy_box = polygon_to_xyxy(polygon)\n                xyxy_list.append(xyxy_box)\n            # per-class labels also provided, but they are [\"\", \"\", \"\", ...]\n            # when we figure out how to set class names, we can do\n            # zip(result[\"labels\"], result[\"polygons\"])\n        xyxy = np.array(xyxy_list, dtype=np.float32)\n        masks = np.array(masks_list)\n        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","sourceCodeStart":570,"sourceCodeEnd":606,"githubUrl":"https://github.com/roboflow/supervision/blob/7f254d9784d4c37e0f03cd89ddee164c8db099c0/src/supervision/detection/vlm.py#L570-L606","documentation":"Raised by the Florence-2 post-processing helper in supervision's VLM module when a '<REGION_TO_CATEGORY>' or '<REGION_TO_DESCRIPTION>' task returns something other than a Python string. The parser expects raw text output from the model (e.g. 'a dog<loc_250><loc_100><loc_600><loc_450>') and cannot proceed with a dict or list. This almost always means the Florence-2 model was invoked with the wrong task prompt for the output it produced.","triggerScenarios":"Calling sv.Detections.from_florence_2(result, task='<REGION_TO_CATEGORY>') or '<REGION_TO_DESCRIPTION>' where result is a dict/list (e.g. the model actually ran '<OD>' or '<OPEN_VOCABULARY_DETECTION>', which return dicts) or a batched/decoded object that is not a plain str.","commonSituations":"Copying a task string from one Florence-2 example but a result object from another; post-processing outputs from a different task than the one used for inference; upgrading transformers so the processor returns ProcessedOutput objects instead of strings.","solutions":["Make sure the task passed to from_florence_2 is exactly the task prompt sent to the model (e.g. '<REGION_TO_CATEGORY>' both at inference and at parsing).","Extract the decoded text first: pass result['<REGION_TO_CATEGORY>'] or processor.decode(...) output rather than the whole result dict.","If you actually ran a grounding/detection task, use the matching task token ('<OD>', '<OPEN_VOCABULARY_DETECTION>', '<CAPTION_TO_PHRASE_GROUNDING>') instead.","Add an isinstance(result, str) check before calling and log type(result) to identify the mismatch."],"exampleFix":"# before\n detections = sv.Detections.from_florence_2(\n     result=parsed_answer, task=\"<REGION_TO_CATEGORY>\"\n )\n\n# after\n detections = sv.Detections.from_florence_2(\n     result=parsed_answer[\"<REGION_TO_CATEGORY>\"],\n     task=\"<REGION_TO_CATEGORY>\",\n )","handlingStrategy":"type-guard","validationCode":"from typing import Any\n\nraw = parsed_answer[\"<REGION_TO_CATEGORY>\"] if isinstance(parsed_answer, dict) else parsed_answer\nif not isinstance(raw, str):\n    raise TypeError(f\"Expected decoded string, got {type(raw)}\")","typeGuard":"def is_florence2_text_result(result: Any) -> bool:\n    return isinstance(result, str)","tryCatchPattern":"try:\n    detections = sv.Detections.from_florence_2(result=raw, task=\"<REGION_TO_CATEGORY>\")\nexcept ValueError as e:\n    logger.warning(\"Skipping frame: Florence-2 result/task mismatch: %s\", e)\n    detections = sv.Detections.empty()","preventionTips":["Keep the task token in a single variable used for both inference and parsing.","Extract the per-task entry from the Florence-2 result dict before calling from_florence_2.","Log type(result) once when integrating a new checkpoint."],"tags":["florence-2","vlm","task-mismatch","validation"],"backgroundTag":null,"analyzedSha":"7f254d9784d4c37e0f03cd89ddee164c8db099c0","analyzedAt":"2026-08-15T05:13:01.950Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}