{"record":{"id":"8f004d9e61800d5b","repo":"docling-project/docling","slug":"expected-scalar-like-ndarray-with-size-1-got-shap","errorCode":null,"errorMessage":"Expected scalar-like ndarray with size 1, got shape={value.shape}","messagePattern":"Expected scalar-like ndarray with size 1, got shape=(.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"docling/models/inference_engines/common/hf_vision_base.py","lineNumber":119,"sourceCode":"                for label_id, label_name in config.id2label.items()\n            }\n        except Exception as exc:\n            raise RuntimeError(\n                f\"Failed to load label mapping from model config at {model_folder}: {exc}\"\n            )\n\n    def get_label_mapping(self) -> Dict[int, str]:\n        \"\"\"Get the label mapping for this model.\"\"\"\n        return self._id_to_label\n\n    @staticmethod\n    def _as_float(value: Any) -> float:\n        if isinstance(value, Real):\n            return float(value)\n\n        if isinstance(value, np.ndarray):\n            if value.size != 1:\n                raise TypeError(\n                    f\"Expected scalar-like ndarray with size 1, got shape={value.shape}\"\n                )\n            return float(value.reshape(-1)[0])\n\n        import torch\n\n        if isinstance(value, torch.Tensor):\n            if value.numel() != 1:\n                raise TypeError(\n                    f\"Expected scalar-like tensor with one element, got shape={tuple(value.shape)}\"\n                )\n            return float(value.item())\n\n        raise TypeError(f\"Unsupported score value type: {type(value)!r}\")\n\n    @staticmethod\n    def _as_int(value: Any) -> int:\n        if isinstance(value, Integral):","sourceCodeStart":101,"sourceCodeEnd":137,"githubUrl":"https://github.com/docling-project/docling/blob/61d76f1ff3f8428065465889f7b4577da7df704c/docling/models/inference_engines/common/hf_vision_base.py#L101-L137","documentation":"Raised as TypeError by HfVisionModelMixin._as_float when a numpy ndarray score does not contain exactly one element. Model outputs are expected to be scalar-like (e.g. per-box score arrays squeezed to size 1); a multi-element array means the post-processing passed an un-reduced slice.","triggerScenarios":"A detection result's score field is an np.ndarray with size != 1 (e.g. a raw [1, N] or [N] logits/softmax slice) when it reaches score conversion.","commonSituations":"Custom model heads or post-processors returning per-class score vectors instead of the selected class score; shape regressions after changing batch post-processing code.","solutions":["Squeeze/select the scalar before conversion: pass score[cls_idx] or float(scores.max()) instead of the row.","Fix the post-processor to emit one scalar score per detection box.","If you control the model wrapper, ensure inference output shapes match the expected [num_detections] score vector."],"exampleFix":"# before\nscore = scores[row]          # ndarray of per-class scores\nconf = model._as_float(score)  # TypeError shape=(num_classes,)\n\n# after\ncls = int(labels[row])\nconf = model._as_float(scores[row, cls])  # single element","handlingStrategy":"type-guard","validationCode":"import numpy as np\nif isinstance(score, np.ndarray):\n    assert score.size == 1, f'score must be scalar-like, got {score.shape}'","typeGuard":"import numpy as np\n\ndef is_scalar_score(value) -> bool:\n    return not isinstance(value, np.ndarray) or value.size == 1","tryCatchPattern":null,"preventionTips":["Reduce per-class arrays to the selected class score before building results.","Unit-test post-processing with real model output shapes.","Log shapes once during development to pin the expected layout."],"tags":["numpy","post-processing","scores","type-error"],"backgroundTag":null,"analyzedSha":"61d76f1ff3f8428065465889f7b4577da7df704c","analyzedAt":"2026-08-14T23:53:18.727Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}