cocoindex-io/cocoindex · error · ValueError

Expected self argument

Error message

Expected self argument

What it means

When a Function was declared to take a self argument (e.g. a method used via coco.fn), _execute expects the first positional argument to be the bound self instance. It throws ValueError when zero positional args are supplied, because self cannot be extracted.

Source

Thrown at python/cocoindex/_internal/function.py:1475

                parent_ctx._core_fn_call_ctx.join_child(fn_ctx)

    async def _execute(
        self,
        async_ctx: core.AsyncContext,
        *args: P.args,
        **kwargs: P.kwargs,
    ) -> R_co:
        """Execute via batcher/runner."""
        if not self._is_scheduled:
            if self._orig_async_fn is not None:
                return await self._orig_async_fn(*args, **kwargs)  # type: ignore
            else:
                assert self._orig_sync_fn is not None
                return await asyncio.to_thread(self._orig_sync_fn, *args, **kwargs)

        if self._has_self:
            if len(args) < 1:
                raise ValueError("Expected self argument")
            self_obj = args[0]
            actual_args = args[1:]
        else:
            self_obj = None
            actual_args = args

        # Parse args based on mode
        if self._batching:
            if len(actual_args) < 1:
                raise ValueError("Expected at least one input argument")
            input_val = actual_args[0]
            extra_args = tuple(actual_args[1:])
            extra_kwargs = dict(kwargs)
        else:
            # Runner-only mode: wrap (args, kwargs) as single input
            input_val = (actual_args, kwargs)
            extra_args = ()
            extra_kwargs = {}

View on GitHub (pinned to e84aa99b32)

Solutions

  1. Pass the instance as the first positional argument when calling the wrapped function.
  2. If the fn is not meant to be a method, re-declare it so _has_self is False (plain function).
  3. Use the bound method (obj.method) rather than the unbound class function so self is already bound.

Example fix

// before
result = await my_fn(arg1=1)  # self missing
// after
result = await my_fn(obj, 1)  # or: await obj.method(1)
Defensive patterns

Strategy: validation

Validate before calling

if fn_meta.has_self and len(positional_args) < 1:
    raise ValueError("instance required as first argument")

Type guard

def has_self_arg(fn): return inspect.signature(fn).parameters and 'self' in inspect.signature(fn).parameters

Try / catch

try:
    result = await wrapped_fn(*args)
except ValueError as e:
    if "Expected self argument" in str(e):
        result = await wrapped_fn(instance, *args)

Prevention

When it happens

Trigger: Calling a coco.fn-wrapped method (or triggering its execution through __call__ / the core processor) with no positional arguments when self._has_self is True — e.g. calling the unbound function with only keyword args, or invoking a method-style fn without its instance.

Common situations: Wrapping an instance method as a standalone @coco.fn and then calling it without the instance; passing all inputs as kwargs so the positional slot for self is empty; refactoring a plain function into a method without updating call sites.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


AI-assisted analysis of cocoindex-io/cocoindex@e84aa99b32 (2026-09-08). Data as JSON: /api/errors/ea1dedf75e3a4f2e. Report an issue: GitHub.