github/copilot-sdk · error · ValueError
on_permission_request must be callable when provided.
Error message
on_permission_request must be callable when provided.
What it means
start_session() validates its keyword arguments before creating a session. If `on_permission_request` is supplied it must be a callable (an async or sync handler invoked for permission prompts); passing a non-callable such as a string, bool, or None-like sentinel raises this ValueError immediately. This is fail-fast argument validation to prevent a broken callback surfacing later mid-session.
Solutions
- Pass an actual callable, e.g. `on_permission_request=PermissionHandler.approve_all` or your own `async def handler(req): ...`.
- Pass None (or omit) if you don't want a permission handler.
- Add a `callable(handler)` check at your config layer before constructing the session.
Example fix
// before await client.start_session(on_permission_request="approve_all") // after await client.start_session(on_permission_request=PermissionHandler.approve_all)
Defensive patterns
Strategy: validation
Validate before calling
if on_permission_request is not None and not callable(on_permission_request):
raise TypeError("on_permission_request must be callable or None") Type guard
def is_permission_handler(value) -> bool:
return value is None or callable(value) Try / catch
try:
session = await client.start_session(on_permission_request=handler)
except ValueError as e:
if "on_permission_request" in str(e):
raise ConfigError("permission handler must be a callable") from e
raise Prevention
- Always pass bound methods or functions, e.g. PermissionHandler.approve_all
- Validate handler config with callable() before session creation
- Avoid stringly-typed handler names in config — resolve them to callables first
When it happens
Trigger: Calling `client.start_session(on_permission_request="approve_all")` or passing a class/method object that isn't bound-callable, a constant, or a wrongly-named attribute.
Common situations: Passing the docstring-style value instead of `PermissionHandler.approve_all`; passing a decorated function that returned a non-callable; mixing up argument order so a string lands in on_permission_request.
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
- telemetry is not supported with…
- Invalid entry '*': there is no bare wildcard. Use one or…
- Client is not connected. Call start() first.
- Set environment variables via either the client-level env…
- connectionToken must be a non-empty string
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/107d865366a2c695.
Report an issue: GitHub.
Appendix: source
Thrown at python/copilot/client.py:2531
A :class:`CopilotSession` instance for the new session.
Raises:
ValueError: If ``on_permission_request`` is provided but not callable.
Example:
>>> session = await client.create_session(
... on_permission_request=PermissionHandler.approve_all,
... )
>>>
>>> # Session with model and streaming
>>> session = await client.create_session(
... on_permission_request=PermissionHandler.approve_all,
... model="gpt-4",
... streaming=True,
... )
"""
if on_permission_request is not None and not callable(on_permission_request):
raise ValueError("on_permission_request must be callable when provided.")
if github_token is not None and github_token_provider is not None:
raise ValueError("github_token and github_token_provider are mutually exclusive")
if ask_user_variant not in (None, "legacy", "elicitation"):
raise ValueError('ask_user_variant must be "legacy" or "elicitation"')
if not self._client:
await self.start()
tool_defs = []
if tools:
for tool in tools:
definition: dict[str, Any] = {
"name": tool.name,
"description": tool.description,
}
if tool.parameters:
definition["parameters"] = tool.parameters
if tool.overrides_built_in_tool:
definition["overridesBuiltInTool"] = TrueView on GitHub (pinned to cd8cf15dc3)