ultralytics/yolov5 · error · RuntimeError
Expected {len(placeholders)} inputs, got {args_len}.
Error message
Expected {len(placeholders)} inputs, got {args_len}. What it means
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.
Source
Thrown at utils/triton.py:71
response = self.client.infer(model_name=self.model_name, inputs=inputs)
result = []
for output in self.metadata["outputs"]:
tensor = torch.as_tensor(response.as_numpy(output["name"]))
result.append(tensor)
return result[0] if len(result) == 1 else result
def _create_inputs(self, *args, **kwargs):
"""Creates input tensors from args or kwargs, not both; raises error if none or both are provided."""
args_len, kwargs_len = len(args), len(kwargs)
if not args_len and not kwargs_len:
raise RuntimeError("No inputs provided.")
if args_len and kwargs_len:
raise RuntimeError("Cannot specify args and kwargs at the same time")
placeholders = self._create_input_placeholders_fn()
if args_len:
if args_len != len(placeholders):
raise RuntimeError(f"Expected {len(placeholders)} inputs, got {args_len}.")
for input, value in zip(placeholders, args):
input.set_data_from_numpy(value.cpu().numpy())
else:
for input in placeholders:
value = kwargs[input.name]
input.set_data_from_numpy(value.cpu().numpy())
return placeholders
View on GitHub (pinned to 20d1d78a08)
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.
Example fix
# before outputs = model(img, img) # model declares 1 input 'images' # after outputs = model(img)
Defensive patterns
Strategy: validation
Validate before calling
expected = len(client.metadata["inputs"]) # or from model config
if len(args) != expected:
raise ValueError(
f"Model declares {expected} inputs ({[i['name'] for i in client.metadata['inputs']]}); "
f"got {len(args)} positional tensors."
)
outputs = triton_model(*args) Type guard
def matches_triton_input_count(args: tuple, input_names: list) -> bool:
"""True when positional tensor count equals the model's declared inputs."""
return len(args) == len(input_names) Try / catch
try:
outputs = triton_model(*tensors)
except RuntimeError as e:
if "inputs, got" in str(e):
names = [i["name"] for i in client.metadata["inputs"]]
raise ValueError(f"Pass exactly {len(names)} tensors, keyed by {names}") from e
raise Prevention
- 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.
When it happens
Trigger: 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().
Common situations: 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.
Related errors
- No inputs provided.
- Cannot specify args and kwargs at the same time
- Source path '{source}' does not exist
- TensorRT engine deserialization failed. Re-export the engine
- ERROR: YOLOv5 TF.js inference is not supported
AI-assisted analysis of ultralytics/yolov5@20d1d78a08 (2026-08-15).
Data as JSON: /api/errors/50d62f045db57797.
Report an issue: GitHub.