github/copilot-sdk · error · ValueError

Invalid arguments: use on_lifecycle(handler) or…

Error message

Invalid arguments: use on_lifecycle(handler) or on_lifecycle(event_type, handler)

What it means

on_lifecycle() supports two overloads: on_lifecycle(handler) for all events, or on_lifecycle(event_type, handler) for a specific event type. If neither signature matches (e.g. zero arguments, three arguments, or two non-handler-first args), the client raises this ValueError.

Solutions

  1. Call on_lifecycle(handler) with exactly one handler for all lifecycle events
  2. Or call on_lifecycle(event_type, handler) with the event type first, using the SessionLifecycleEventType enum value
  3. Remove keyword arguments; the dispatcher matches positional overloads only
  4. Swap argument order if you wrote on_lifecycle(handler, event_type)

Example fix

// before
client.on_lifecycle("session.created", on_created)
// after
from copilot.generated.protocol import SessionLifecycleEventType
client.on_lifecycle(SessionLifecycleEventType.SESSION_CREATED, on_created)
Defensive patterns

Strategy: validation

Validate before calling

from copilot.generated.protocol import SessionLifecycleEventType
assert isinstance(event_type, SessionLifecycleEventType)
assert callable(handler)
client.on_lifecycle(event_type, handler)

Type guard

def is_valid_lifecycle_args(*args) -> bool:
    return len(args) == 1 and callable(args[0]) or (
        len(args) == 2 and isinstance(args[0], SessionLifecycleEventType) and callable(args[1])
    )

Try / catch

try:
    client.on_lifecycle(event_type, handler)
except ValueError as e:
    if "Invalid arguments" in str(e):
        client.on_lifecycle(handler)  # fall back to all-events subscription
    else:
        raise

Prevention

When it happens

Trigger: Calling client.on_lifecycle() with no arguments, with more than two arguments, or with two positional arguments where the first is not a recognized SessionLifecycleEventType (e.g. passing a string event name).

Common situations: Passing event type as a raw string like "session.created" instead of the enum; passing keyword arguments (handler=...) which the positional-overload dispatcher doesn't recognize; typos in argument order like on_lifecycle(handler, event_type).

Understand the failure class

Background: "must be a positive integer", "cannot be empty", "invalid argument": how invalid-argument errors work across open-source libraries — this error's family across 33 libraries.

Related errors


AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09). Data as JSON: /api/errors/b34f0b2cebc0af6c. Report an issue: GitHub.

Appendix: source

Thrown at python/copilot/client.py:4071

                            self._lifecycle_handlers.remove(wildcard_handler)

                return unsubscribe_wildcard
            elif isinstance(event_type_or_handler, str) and handler is not None:
                # Typed subscription: on(event_type, handler)
                event_type = cast(SessionLifecycleEventType, event_type_or_handler)
                if event_type not in self._typed_lifecycle_handlers:
                    self._typed_lifecycle_handlers[event_type] = []
                self._typed_lifecycle_handlers[event_type].append(handler)

                def unsubscribe_typed() -> None:
                    with self._lifecycle_handlers_lock:
                        handlers = self._typed_lifecycle_handlers.get(event_type, [])
                        if handler in handlers:
                            handlers.remove(handler)

                return unsubscribe_typed
            else:
                raise ValueError(
                    "Invalid arguments: use on_lifecycle(handler) "
                    "or on_lifecycle(event_type, handler)"
                )

    def _dispatch_lifecycle_event(self, event: SessionLifecycleEvent) -> None:
        """Dispatch a lifecycle event to all registered handlers."""
        with self._lifecycle_handlers_lock:
            # Copy handlers to avoid holding lock during callbacks
            typed_handlers = list(self._typed_lifecycle_handlers.get(event.type, []))
            wildcard_handlers = list(self._lifecycle_handlers)

        # Dispatch to typed handlers
        for handler in typed_handlers:
            try:
                handler(event)
            except Exception:
                pass  # Ignore handler errors

View on GitHub (pinned to cd8cf15dc3)