{"record":{"id":"50d62f045db57797","repo":"ultralytics/yolov5","slug":"expected-len-placeholders-inputs-got-args-len","errorCode":null,"errorMessage":"Expected {len(placeholders)} inputs, got {args_len}.","messagePattern":"Expected (.+?) inputs, got (.+?)\\.","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"utils/triton.py","lineNumber":71,"sourceCode":"        response = self.client.infer(model_name=self.model_name, inputs=inputs)\n        result = []\n        for output in self.metadata[\"outputs\"]:\n            tensor = torch.as_tensor(response.as_numpy(output[\"name\"]))\n            result.append(tensor)\n        return result[0] if len(result) == 1 else result\n\n    def _create_inputs(self, *args, **kwargs):\n        \"\"\"Creates input tensors from args or kwargs, not both; raises error if none or both are provided.\"\"\"\n        args_len, kwargs_len = len(args), len(kwargs)\n        if not args_len and not kwargs_len:\n            raise RuntimeError(\"No inputs provided.\")\n        if args_len and kwargs_len:\n            raise RuntimeError(\"Cannot specify args and kwargs at the same time\")\n\n        placeholders = self._create_input_placeholders_fn()\n        if args_len:\n            if args_len != len(placeholders):\n                raise RuntimeError(f\"Expected {len(placeholders)} inputs, got {args_len}.\")\n            for input, value in zip(placeholders, args):\n                input.set_data_from_numpy(value.cpu().numpy())\n        else:\n            for input in placeholders:\n                value = kwargs[input.name]\n                input.set_data_from_numpy(value.cpu().numpy())\n        return placeholders\n","sourceCodeStart":53,"sourceCodeEnd":79,"githubUrl":"https://github.com/ultralytics/yolov5/blob/20d1d78a08277e365d57bfa3a2cce752772d9e59/utils/triton.py#L53-L79","documentation":"Raised by TritonClient._create_inputs (utils/triton.py) when positional args are used and their count does not equal the number of input placeholders the Triton model declares. Positional inputs are zipped 1:1 with the server's config, so the counts must match exactly (e.g. a single-'images' model requires exactly one tensor). Note the f-string was quoted in the source, so the message renders literally with '{len(placeholders)}' unexpanded.","triggerScenarios":"Calling a Triton-wrapped model with the wrong number of positional tensors: model(img, extra_tensor) for a model with one input, or model(img) for an ensemble model with two declared inputs. The placeholder list comes from the server's model config via _create_input_placeholders_fn().","commonSituations":"Ensemble or multi-input Triton models (image + metadata) invoked with only the image; a pipeline refactored from one input to several without updating the caller; passing a list as a single positional arg instead of unpacking (model(batch) vs model(*batch)); mismatch between the model version deployed on the server and the client's expectations.","solutions":["Query the model's declared inputs and pass exactly that many positional tensors: print(client.metadata['inputs']) or check the model config on the Triton server.","Unpack batch lists correctly: model(*batch) when batch is a list of input tensors, not model(batch).","If the model genuinely has multiple inputs, prefer keyword form keyed by input name (model(images=img, metadata=meta)) to avoid ordering mistakes.","Verify the deployed model version/config matches what the client code was written for."],"exampleFix":"# before\noutputs = model(img, img)  # model declares 1 input 'images'\n# after\noutputs = model(img)","handlingStrategy":"validation","validationCode":"expected = len(client.metadata[\"inputs\"])  # or from model config\nif len(args) != expected:\n    raise ValueError(\n        f\"Model declares {expected} inputs ({[i['name'] for i in client.metadata['inputs']]}); \"\n        f\"got {len(args)} positional tensors.\"\n    )\noutputs = triton_model(*args)","typeGuard":"def matches_triton_input_count(args: tuple, input_names: list) -> bool:\n    \"\"\"True when positional tensor count equals the model's declared inputs.\"\"\"\n    return len(args) == len(input_names)","tryCatchPattern":"try:\n    outputs = triton_model(*tensors)\nexcept RuntimeError as e:\n    if \"inputs, got\" in str(e):\n        names = [i[\"name\"] for i in client.metadata[\"inputs\"]]\n        raise ValueError(f\"Pass exactly {len(names)} tensors, keyed by {names}\") from e\n    raise","preventionTips":["Fetch and cache the model's input list (names and arity) once at client startup and validate every request against it.","Unpack lists with model(*batch), never model(batch).","Prefer keyword inputs keyed by declared input names for multi-input/ensemble models."],"tags":["triton","inference","client","input-validation","model-config"],"backgroundTag":null,"analyzedSha":"20d1d78a08277e365d57bfa3a2cce752772d9e59","analyzedAt":"2026-08-15T02:56:15.443Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}