{"record":{"id":"e361f87a80908aeb","repo":"github/copilot-sdk","slug":"missing-required-fields-in-pingresponse-message","errorCode":null,"errorMessage":"Missing required fields in PingResponse: message={message}, timestamp={timestamp}, protocolVersion={protocol_version}","messagePattern":"Missing required fields in PingResponse: message=(.+?), timestamp=(.+?), protocolVersion=(.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"python/copilot/client.py","lineNumber":849,"sourceCode":"# ============================================================================\n\n\n@dataclass\nclass PingResponse:\n    \"\"\"Response from ping\"\"\"\n\n    message: str  # Echo message with \"pong: \" prefix\n    timestamp: datetime  # Timestamp when the ping was processed\n    protocol_version: int  # Protocol version for SDK compatibility\n\n    @staticmethod\n    def from_dict(obj: Any) -> PingResponse:\n        assert isinstance(obj, dict)\n        message = obj.get(\"message\")\n        timestamp = obj.get(\"timestamp\")\n        protocol_version = obj.get(\"protocolVersion\")\n        if message is None or timestamp is None or protocol_version is None:\n            raise ValueError(\n                f\"Missing required fields in PingResponse: message={message}, \"\n                f\"timestamp={timestamp}, protocolVersion={protocol_version}\"\n            )\n        timestamp_value = (\n            datetime.fromtimestamp(timestamp / 1000, tz=UTC)\n            if isinstance(timestamp, (int, float))\n            else from_datetime(timestamp)\n        )\n        return PingResponse(str(message), timestamp_value, int(protocol_version))\n\n    def to_dict(self) -> dict:\n        result: dict = {}\n        result[\"message\"] = self.message\n        result[\"timestamp\"] = self.timestamp.isoformat()\n        result[\"protocolVersion\"] = self.protocol_version\n        return result\n\n","sourceCodeStart":831,"sourceCodeEnd":867,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/python/copilot/client.py#L831-L867","documentation":"PingResponse.from_dict validates the raw JSON-RPC payload from the server and requires 'message', 'timestamp' (epoch millis), and 'protocolVersion' to be present. If any is missing/None it raises ValueError listing the offending values. This guards against decoding an incomplete or malformed ping response into a dataclass.","triggerScenarios":"The server (or a proxy/test stub) returns a ping payload omitting message, timestamp, or protocolVersion; a mock returning partial dicts; a protocol downgrade where older servers omit protocolVersion.","commonSituations":"Pinning against an older server build whose ping schema differs; unit-test fakes that return {'message': 'pong'} only; custom middleware stripping fields; version mismatch between client expectations and server build.","solutions":["Upgrade/align the Copilot server so its ping response includes message, timestamp, and protocolVersion","Fix test mocks/stubs to return all three fields (timestamp as int/float epoch milliseconds)","Check for proxies or response-rewriting middleware that drop fields","Verify client and server protocol versions match"],"exampleFix":"// before (test stub)\nreturn {\"message\": \"pong\"}\n// after\nimport time\nreturn {\"message\": \"pong\", \"timestamp\": int(time.time() * 1000), \"protocolVersion\": 1}","handlingStrategy":"try-catch","validationCode":"def is_valid_ping_payload(obj) -> bool:\n    return isinstance(obj, dict) and all(obj.get(k) is not None for k in (\"message\", \"timestamp\", \"protocolVersion\"))","typeGuard":"def is_ping_response(obj: object) -> bool:\n    return (\n        isinstance(obj, dict)\n        and isinstance(obj.get(\"message\"), str)\n        and isinstance(obj.get(\"timestamp\"), (int, float))\n        and \"protocolVersion\" in obj\n    )","tryCatchPattern":"try:\n    ping = PingResponse.from_dict(payload)\nexcept ValueError as e:\n    if str(e).startswith(\"Missing required fields in PingResponse\"):\n        logger.error(\"malformed ping payload: %s\", payload)\n        ping = None  # or reconnect / re-handshake\n    else:\n        raise","preventionTips":["Keep server and client on compatible protocol versions","Make test stubs mirror the full production ping schema","Validate raw JSON payloads against the expected shape before decoding"],"tags":["python","deserialization","ping","schema"],"backgroundTag":"schema-validation-failed","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-16T04:17:20.429Z"}