{"record":{"id":"1009994eed5fa090","repo":"cocoindex-io/cocoindex","slug":"expected-at-least-one-input-argument","errorCode":null,"errorMessage":"Expected at least one input argument","messagePattern":"Expected at least one input argument","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/cocoindex/_internal/function.py","lineNumber":1485,"sourceCode":"            if self._orig_async_fn is not None:\n                return await self._orig_async_fn(*args, **kwargs)  # type: ignore\n            else:\n                assert self._orig_sync_fn is not None\n                return await asyncio.to_thread(self._orig_sync_fn, *args, **kwargs)\n\n        if self._has_self:\n            if len(args) < 1:\n                raise ValueError(\"Expected self argument\")\n            self_obj = args[0]\n            actual_args = args[1:]\n        else:\n            self_obj = None\n            actual_args = args\n\n        # Parse args based on mode\n        if self._batching:\n            if len(actual_args) < 1:\n                raise ValueError(\"Expected at least one input argument\")\n            input_val = actual_args[0]\n            extra_args = tuple(actual_args[1:])\n            extra_kwargs = dict(kwargs)\n        else:\n            # Runner-only mode: wrap (args, kwargs) as single input\n            input_val = (actual_args, kwargs)\n            extra_args = ()\n            extra_kwargs = {}\n\n        batcher_key, batcher = self._acquire_batcher(\n            async_ctx, self_obj, extra_args, extra_kwargs\n        )\n        try:\n            result = await batcher.run(input_val)\n            _deadline_checkpoint()\n        finally:\n            self._release_batcher(batcher_key)\n        # After a RetryWithSmallerBatch split, a failed sub-batch delivers its","sourceCodeStart":1467,"sourceCodeEnd":1503,"githubUrl":"https://github.com/cocoindex-io/cocoindex/blob/e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b/python/cocoindex/_internal/function.py#L1467-L1503","documentation":"In batching mode, the wrapped function receives a batch as its first positional argument. _execute requires at least one positional argument to form that batch input; calling a batching coco.fn with zero positional arguments raises this ValueError.","triggerScenarios":"Calling a function declared with batching=True (via coco.fn batching mode) with no positional args, e.g. fn() or fn(key=value) only; empty positional list forwarded by the core processor.","commonSituations":"Switching a function to batching mode and forgetting that callers must pass the batch/iterable as the first positional argument; a dispatcher that builds args dynamically and produces an empty tuple.","solutions":["Pass the batch (list/iterable of inputs) as the first positional argument.","If the function is not meant to batch, remove batching=True from the decorator.","Fix dynamic call sites to always include at least one positional input."],"exampleFix":"// before\nresult = await batched_fn()\n// after\nresult = await batched_fn([item1, item2])","handlingStrategy":"validation","validationCode":"if batching and len(args) < 1:\n    raise ValueError(\"batching fn needs the batch as first positional arg\")","typeGuard":null,"tryCatchPattern":"try:\n    out = await batched_fn(*args)\nexcept ValueError as e:\n    if \"at least one input argument\" in str(e):\n        out = await batched_fn(items)","preventionTips":["Remember batching-mode fns take the batch as the first positional argument.","Audit dynamic dispatchers to guarantee a non-empty positional args tuple."],"tags":["python","batching","argument-mismatch"],"backgroundTag":"missing-required-argument","analyzedSha":"e84aa99b3292c5270a4b313b2a7137ad9ce8ab3b","analyzedAt":"2026-09-08T15:59:19.997Z","contentChangedAt":"2026-09-08T15:59:19.997Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}