{"record":{"id":"65e907ce01d26fac","repo":"github/copilot-sdk","slug":"failed-to-deserialize-session-canvas-opened-payloa","errorCode":null,"errorMessage":"failed to deserialize session.canvas.opened payload","messagePattern":"failed to deserialize session\\.canvas\\.opened payload","errorType":"console","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"nodejs/src/session.ts","lineNumber":1075,"sourceCode":"                        mode,\n                        elicitationSource,\n                        url,\n                    },\n                    requestId\n                );\n            }\n        } else if (event.type === \"capabilities.changed\") {\n            this._capabilities = { ...this._capabilities, ...event.data };\n        } else if (event.type === \"session.canvas.opened\") {\n            this.upsertOpenCanvasFromEvent(event.data);\n        } else if (event.type === \"session.canvas.closed\") {\n            this.removeOpenCanvasFromEvent(event.data);\n        }\n    }\n\n    private upsertOpenCanvasFromEvent(data: unknown): void {\n        if (!isOpenCanvasInstance(data)) {\n            console.warn(\"failed to deserialize session.canvas.opened payload\");\n            return;\n        }\n        this.upsertOpenCanvas(data);\n    }\n\n    private removeOpenCanvasFromEvent(data: unknown): void {\n        if (\n            !data ||\n            typeof data !== \"object\" ||\n            typeof (data as { instanceId?: unknown }).instanceId !== \"string\" ||\n            (data as { instanceId: string }).instanceId.length === 0\n        ) {\n            console.warn(\"failed to deserialize session.canvas.closed payload\");\n            return;\n        }\n        this.removeOpenCanvas((data as { instanceId: string }).instanceId);\n    }\n","sourceCodeStart":1057,"sourceCodeEnd":1093,"githubUrl":"https://github.com/github/copilot-sdk/blob/cd8cf15dc3f9e762615790aaed0a771a0f392755/nodejs/src/session.ts#L1057-L1093","documentation":"When a session.canvas.opened event arrives, CopilotSession validates the payload with isOpenCanvasInstance before updating its internal open-canvas state. If the payload does not match the expected canvas instance shape, the session logs this warning and skips the upsert, so the canvas will not appear in tracked open canvases.","triggerScenarios":"Server sends a session.canvas.opened event whose data is missing required fields or has wrong types (e.g. not a valid canvas instance object), typically due to a server/client version mismatch or corrupted event payload.","commonSituations":"Running an older client against a newer server that changed the canvas payload schema; a proxy or custom transport mangling JSON; third-party event replay with partial payloads.","solutions":["Upgrade the SDK and server to matching versions so the canvas payload schema aligns.","Log the raw event data (patch or wrap the event handler) to see which field failed the isOpenCanvasInstance check.","If events come from a custom transport, verify JSON serialization is not dropping or altering fields.","If you control the payload producer, validate it against the expected canvas instance shape before emitting."],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"function isValidCanvasPayload(d: unknown): boolean {\n  return typeof d === 'object' && d !== null && typeof (d as any).instanceId === 'string';\n}","typeGuard":"function isOpenCanvasInstance(v: unknown): v is CanvasInstance {\n  return (\n    typeof v === 'object' &&\n    v !== null &&\n    typeof (v as { instanceId?: unknown }).instanceId === 'string' &&\n    (v as { instanceId: string }).instanceId.length > 0\n  );\n}","tryCatchPattern":"// event-based; guard before use\nif (isOpenCanvasInstance(event.data)) {\n  trackCanvas(event.data);\n} else {\n  console.warn('skipping malformed canvas.opened payload', event.data);\n}","preventionTips":["Keep SDK and server versions aligned","Validate canvas payloads at the transport boundary","Log raw payloads for schema drift detection"],"tags":["deserialization","canvas","schema","event"],"backgroundTag":"unexpected-response-shape","analyzedSha":"cd8cf15dc3f9e762615790aaed0a771a0f392755","analyzedAt":"2026-09-09T18:32:31.973Z","contentChangedAt":"2026-09-09T18:32:31.973Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}