cocoindex-io/cocoindex · error · ValueError
Batching and runner require the function to be async. Use @c
Error message
Batching and runner require the function to be async. Use @coco.fn.as_async instead, or rewrite the function to be async.
What it means
The sync builder path (_build_sync, used by @coco.fn for plain sync functions) cannot support batching= or runner=, which require asynchronous execution. Applying such a decorator configuration to a sync function raises ValueError at decoration time.
Source
Thrown at python/cocoindex/_internal/function.py:1850
batching: bool = False,
max_batch_size: int | None = None,
runner: Runner | None = None,
version: int | None = None,
logic_tracking: LogicTracking = "full",
deps: Any = None,
) -> None:
self._memo = memo
self._memo_key = memo_key
self._batching = batching
self._max_batch_size = max_batch_size
self._runner = runner
self._version = version
self._logic_tracking = logic_tracking
self._deps = deps
def _build_sync(self, fn: Callable[P, R_co]) -> SyncFunction[P, R_co]:
if self._batching or self._runner is not None:
raise ValueError(
"Batching and runner require the function to be async. "
"Use @coco.fn.as_async instead, or rewrite the function to be async."
)
wrapper = SyncFunction(
fn,
memo=self._memo,
memo_key=self._memo_key,
version=self._version,
logic_tracking=self._logic_tracking,
deps=self._deps,
)
functools.update_wrapper(wrapper, fn)
return wrapper
def _build_async(
self,
fn: AnyCallable[P, R_co],
) -> AsyncFunction[P, R_co]:View on GitHub (pinned to e84aa99b32)
Solutions
- Rewrite the function as async def and use @coco.fn.as_async.
- Remove batching=/runner= options if the function should stay sync.
- Keep the function sync and process batches externally with mount_each/map instead.
Example fix
// before @coco.fn(batching=True) def embed(texts): ... // after @coco.fn.as_async(batching=True) async def embed(texts): ...
Defensive patterns
Strategy: validation
Validate before calling
import inspect
if (batching or runner is not None) and not inspect.iscoroutinefunction(fn):
raise TypeError("use @coco.fn.as_async for batching/runner") Type guard
def is_async_fn(fn): return inspect.iscoroutinefunction(fn)
Try / catch
try:
deco = coco.fn(batching=True)(fn)
except ValueError:
deco = coco.fn.as_async(batching=True)(make_async(fn)) Prevention
- Use @coco.fn.as_async whenever batching= or runner= is set.
- Match decorator variant to function kind: def -> coco.fn, async def -> as_async.
When it happens
Trigger: @coco.fn(batching=True) or @coco.fn(runner=...) applied to a def (non-async) function; _build_sync invoked via __call__ with _batching set or _runner non-None.
Common situations: Copying a decorator config that used batching onto a sync function; switching a function from async def to def while keeping batching/runner options; using @coco.fn instead of @coco.fn.as_async for batched processing.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Async functions are not supported by @coco.fn decorator when
- Either async_fn or sync_fn must be provided
- Expected at least one input argument
- @serialize_by_pickle on {cls.__qualname__} (a {'dataclass' i
- use_mount() requires a ComponentSubpath when the function ha
AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08).
Data as JSON: /api/errors/2ed3d14bee819b01.
Report an issue: GitHub.