roboflow/supervision · error · ValueError

Invalid VLM result type

Error message

Invalid VLM result type: {type(result)}. Must be str.

What it means

Inside Detections.from_vlm, the PaliGemma branch parses raw model output text (the <det> token sequence in the PaliGemma prompt format). The parser from_paligemma only accepts str, so any other result type (dict, list, bytes, parsed JSON) raises this ValueError before parsing.

Solutions

  1. Decode the model output to its raw string with special tokens intact: processor.decode(outputs[0], skip_special_tokens=False) — PaliGemma detection tokens (<det>...) must not be stripped.
  2. If the result came from an API wrapper, extract the text field before passing.
  3. Keep skip_special_tokens=False; PaliGemma box tokens are special tokens and are required by the parser.

Example fix

# before
outputs = model.generate(**inputs)
detections = sv.Detections.from_vlm(vlm=sv.VLM.PALIGEMMA, result=outputs)  # tensor

# after
import supervision as sv
text = processor.decode(outputs[0], skip_special_tokens=False)
detections = sv.Detections.from_vlm(vlm=sv.VLM.PALIGEMMA, result=text)
Defensive patterns

Strategy: type-guard

Validate before calling

text = (
    result if isinstance(result, str)
    else processor.decode(result[0], skip_special_tokens=False)
)
assert isinstance(text, str)
detections = sv.Detections.from_vlm(vlm=sv.VLM.PALIGEMMA, result=text)

Type guard

def paligemma_result_str(result) -> bool:
    return isinstance(result, str)

Try / catch

try:
    detections = sv.Detections.from_vlm(vlm=sv.VLM.PALIGEMMA, result=result)
except ValueError as e:
    if 'Must be str' in str(e):
        result = processor.decode(result[0], skip_special_tokens=False)
        detections = sv.Detections.from_vlm(vlm=sv.VLM.PALIGEMMA, result=result)
    else:
        raise

Prevention

When it happens

Trigger: Calling from_vlm(vlm=sv.VLM.PALIGEMMA, result=...) (or from_lmm with lmm='paligemma') where result is a dict, list of tokens, or an object with a .text attribute instead of the decoded string.

Common situations: Passing the transformers generate() tensor output instead of processor.decode(..., skip_special_tokens=False) text; passing a Roboflow/Hosted API response object or dict; pre-parsing the output with json.loads.

Related errors


AI-assisted analysis of roboflow/supervision@7f254d9784 (2026-08-15). Data as JSON: /api/errors/14612510178e9201. Report an issue: GitHub.

Appendix: source

Thrown at src/supervision/detection/core.py:2029

            >>> detections.xyxy
            array([[ 580.58057 ,  270.27026 , 1000.      ,  904.9049  ],
                   [  26.026026,   31.03103 ,  632.6326  ,  998.999   ]],
                  dtype=float32)
            >>> detections.class_id
            array([0, 1])
            >>> detections.data
            {'class_name': array(['The giraffe at the back', 'The giraffe at the front'],
                  dtype='<U24')}

            ```

        """  # noqa: E501

        vlm = _validate_vlm_parameters(vlm, result, kwargs)

        if vlm == VLM.PALIGEMMA:
            if not isinstance(result, str):
                raise ValueError(
                    f"Invalid VLM result type: {type(result)}. Must be str."
                )
            xyxy, class_id, class_name = from_paligemma(result, **kwargs)
            data: _DetectionDataType = {
                CLASS_NAME_DATA_FIELD: class_name,
            }
            return cls(xyxy=xyxy, class_id=class_id, data=data)

        if vlm == VLM.QWEN_2_5_VL:
            if not isinstance(result, str):
                raise ValueError(
                    f"Invalid VLM result type: {type(result)}. Must be str."
                )
            xyxy, class_id, class_name = from_qwen_2_5_vl(result, **kwargs)
            data = {CLASS_NAME_DATA_FIELD: class_name}
            confidence_arr: npt.NDArray[np.floating[Any]] = np.ones(
                len(xyxy), dtype=float
            )

View on GitHub (pinned to 7f254d9784)