Skip to content

ValueError: 'session.usage_info' is not a valid SessionEventType #30

@ewilderj

Description

@ewilderj

Summary

The SDK throws a ValueError when the Copilot server sends session.usage_info events, because this event type is not defined in the SessionEventType enum. The error is printed to stderr as an unhandled exception in the asyncio event loop callback, which creates noisy output even though the request completes successfully.

Reproduction

import asyncio
from copilot import CopilotClient
from copilot.generated.session_events import SessionEventType

async def repro():
    client = CopilotClient()
    await client.start()
    
    try:
        session = await client.create_session({
            "model": "claude-sonnet-4.5",
            "streaming": False,
            "available_tools": [],
        })
        
        done = asyncio.Event()
        
        def handle_event(event):
            if event.type == SessionEventType.ASSISTANT_TURN_END:
                done.set()
        
        unsubscribe = session.on(handle_event)
        
        try:
            await session.send({"prompt": "Say hello"})
            await asyncio.wait_for(done.wait(), timeout=30)
        finally:
            unsubscribe()
            await session.destroy()
    finally:
        await client.stop()

# Run with GH_TOKEN set
asyncio.run(repro())

Output:

Exception in callback CopilotClient._connect_via_stdio.<locals>.handle_notification(...)
Traceback (most recent call last):
  ...
  File ".../copilot/generated/session_events.py", line 618, in from_dict
    type = SessionEventType(obj.get("type"))
ValueError: 'session.usage_info' is not a valid SessionEventType

Root Cause

In copilot/generated/session_events.py, the SessionEventType enum does not include session.usage_info:

class SessionEventType(Enum):
    ASSISTANT_MESSAGE = "session.assistant.message"
    ASSISTANT_MESSAGE_DELTA = "session.assistant.message.delta"
    ASSISTANT_TURN_END = "session.assistant.turn.end"
    # ... other types
    # Missing: SESSION_USAGE_INFO = "session.usage_info"

When SessionEvent.from_dict() tries to parse an event with type: "session.usage_info", it fails:

type = SessionEventType(obj.get("type"))  # ValueError!

Suggested Fix

Option 1: Add the missing event type to the enum:

class SessionEventType(Enum):
    # ... existing types ...
    SESSION_USAGE_INFO = "session.usage_info"

Option 2: Handle unknown event types gracefully in session_event_from_dict():

def session_event_from_dict(s: dict) -> Optional[SessionEvent]:
    try:
        return SessionEvent.from_dict(s)
    except ValueError:
        # Unknown event type - ignore gracefully
        return None

And update handle_notification() to handle None:

def handle_notification(method: str, params: dict):
    if method == "session.event":
        event = session_event_from_dict(event_dict)
        if event is not None:  # Skip unknown event types
            session._dispatch_event(event)

Environment

  • OS: macOS 14.x
  • Python: 3.11
  • SDK version: Latest from pip

Impact

  • Severity: Low (does not break functionality, but creates noisy stderr output)
  • Workaround: Suppress the exception via custom asyncio exception handler

Metadata

Metadata

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions