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.

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.

Appendix: 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)