github/copilot-sdk · error · ValueError
Missing required fields in SessionMetadata: sessionId=
Error message
Missing required fields in SessionMetadata: sessionId={session_id}, startTime={start_time}, modifiedTime={modified_time}, isRemote={is_remote} What it means
SessionMetadata.from_dict requires four mandatory keys: sessionId, startTime, modifiedTime, and isRemote. The library raises ValueError when any of them is absent (None) in the input dict, because a session cannot be tracked without identity and timestamps.
Solutions
- Add all four required keys (sessionId, startTime, modifiedTime, isRemote) to the dict before calling from_dict
- Validate the dict with a helper that checks for the required keys first
- Check the source of the JSON: if it uses snake_case (session_id, start_time), rename keys to camelCase before deserializing
- If the data comes from an old export, regenerate it with a current version of the tool so all fields are present
Example fix
// before
meta = SessionMetadata.from_dict({"sessionId": "s1", "startTime": "2024-01-01"})
# after
meta = SessionMetadata.from_dict({
"sessionId": "s1",
"startTime": "2024-01-01T00:00:00Z",
"modifiedTime": "2024-01-01T01:00:00Z",
"isRemote": False,
}) Defensive patterns
Strategy: validation
Validate before calling
required = {"sessionId", "startTime", "modifiedTime", "isRemote"}
if not required.issubset(data.keys()):
raise ValueError(f"missing: {required - data.keys()}")
SessionMetadata.from_dict(data) Type guard
def has_session_fields(obj: dict) -> bool:
return all(obj.get(k) is not None for k in ("sessionId", "startTime", "modifiedTime", "isRemote")) Try / catch
try:
meta = SessionMetadata.from_dict(data)
except ValueError as e:
logger.error("bad session metadata: %s", e)
meta = None Prevention
- Validate payloads against the SessionMetadata schema before from_dict
- Normalize snake_case keys to camelCase when ingesting external JSON
- Add a round-trip serialization test for session metadata
When it happens
Trigger: Calling SessionMetadata.from_dict() with a dict missing one or more of sessionId/startTime/modifiedTime/isRemote, e.g. deserializing a truncated or hand-crafted session JSON payload.
Common situations: Parsing session files exported by older library versions that lacked modifiedTime; hand-written test fixtures with only partial fields; JSON produced by a different tool that uses snake_case keys instead of camelCase.
Understand the failure class
Background: "is required", "must be set", "missing required field": configuration validation errors across open-source libraries — this error's family across 36 libraries.
Related errors
- agent_id must be a string
- builtin_plugin_directories must contain only absolute paths
- connection_token must be a non-empty string
- invalid entry '*': there is no bare wildcard. Use…
- invalid tool name: must not be empty
AI-assisted analysis of github/copilot-sdk@cd8cf15dc3 (2026-09-09).
Data as JSON: /api/errors/c4cb9045091ff3dd.
Report an issue: GitHub.
Appendix: source
Thrown at python/copilot/client.py:1260
class SessionMetadata:
"""Metadata about a session"""
session_id: str # Session identifier
start_time: datetime # Timestamp when session was created
modified_time: datetime # Timestamp when session was last modified
is_remote: bool # Whether the session is remote
summary: str | None = None # Optional summary of the session
context: SessionContext | None = None # Working directory context
@staticmethod
def from_dict(obj: Any) -> SessionMetadata:
assert isinstance(obj, dict)
session_id = obj.get("sessionId")
start_time = obj.get("startTime")
modified_time = obj.get("modifiedTime")
is_remote = obj.get("isRemote")
if session_id is None or start_time is None or modified_time is None or is_remote is None:
raise ValueError(
f"Missing required fields in SessionMetadata: sessionId={session_id}, "
f"startTime={start_time}, modifiedTime={modified_time}, isRemote={is_remote}"
)
summary = obj.get("summary")
context_dict = obj.get("context")
context = SessionContext.from_dict(context_dict) if context_dict else None
return SessionMetadata(
session_id=str(session_id),
start_time=_parse_session_timestamp(start_time),
modified_time=_parse_session_timestamp(modified_time),
is_remote=bool(is_remote),
summary=summary,
context=context,
)
def to_dict(self) -> dict:
result: dict = {}
result["sessionId"] = self.session_idView on GitHub (pinned to cd8cf15dc3)