{"record":{"id":"e6e3c9253bae83f9","repo":"wavetermdev/waveterm","slug":"no-webcontents-found-with-blockid-data-blockid","errorCode":null,"errorMessage":"no webcontents found with blockid ${data.blockid}","messagePattern":"no webcontents found with blockid (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"warning","filePath":"emain/emain-wsh.ts","lineNumber":28,"sourceCode":"import { getWebContentsByBlockId, webGetSelector } from \"./emain-web\";\nimport { createBrowserWindow, getWaveWindowById, getWaveWindowByWorkspaceId } from \"./emain-window\";\n\nexport class ElectronWshClientType extends WshClient {\n    constructor() {\n        super(\"electron\");\n    }\n\n    async handle_webselector(rh: RpcResponseHelper, data: CommandWebSelectorData): Promise<string[]> {\n        if (!data.tabid || !data.blockid || !data.workspaceid) {\n            throw new Error(\"tabid and blockid are required\");\n        }\n        const ww = getWaveWindowByWorkspaceId(data.workspaceid);\n        if (ww == null) {\n            throw new Error(`no window found with workspace ${data.workspaceid}`);\n        }\n        const wc = await getWebContentsByBlockId(ww, data.tabid, data.blockid);\n        if (wc == null) {\n            throw new Error(`no webcontents found with blockid ${data.blockid}`);\n        }\n        const rtn = await webGetSelector(wc, data.selector, data.opts);\n        return rtn;\n    }\n\n    async handle_notify(rh: RpcResponseHelper, notificationOptions: WaveNotificationOptions) {\n        new Notification({\n            title: notificationOptions.title,\n            body: notificationOptions.body,\n            silent: notificationOptions.silent,\n        }).show();\n    }\n\n    async handle_getupdatechannel(rh: RpcResponseHelper): Promise<string> {\n        return getResolvedUpdateChannel();\n    }\n\n    async handle_focuswindow(rh: RpcResponseHelper, windowId: string) {","sourceCodeStart":10,"sourceCodeEnd":46,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/emain/emain-wsh.ts#L10-L46","documentation":"WslConn.Close waits for any in-flight waiter (a registered goroutine performing connection work) to finish before closing. It polls conn.HasWaiter every 10ms and, if the waiter is still registered after 2 seconds, returns this timeout error instead of closing while work is in progress. Reaching this error means the close was refused, not that the connection failed.","triggerScenarios":"Reconnect (or direct Close) is called while another operation holds the waiter flag for over 2 seconds — e.g. a long-running connserver startup or handshake still in flight.","commonSituations":"Reconnect attempted immediately after a network drop while the connection was still handshaking; slow WSL startup exceeding the 2s window; a waiter goroutine stuck/hung.","solutions":["Wait a moment and retry the Close/Reconnect — the in-flight waiter usually completes","Investigate what is holding HasWaiter (connserver startup, version check) and why it exceeds 2s","If the waiter is permanently stuck, restart the Wave connection/block to clear state","Retry with backoff rather than immediately reconnecting after a status change"],"exampleFix":"// before\nerr := conn.Reconnect(ctx) // can hit waiter timeout during handshake\n// after\nif err := conn.Reconnect(ctx); err != nil && strings.Contains(err.Error(), \"timeout waiting for waiter\") {\n    time.Sleep(3 * time.Second)\n    err = conn.Reconnect(ctx) // retry after in-flight work settles\n}","handlingStrategy":"retry","validationCode":"if conn.HasWaiter.Load() {\n    time.Sleep(3 * time.Second) // let in-flight work finish before closing\n}","typeGuard":null,"tryCatchPattern":"err := conn.Reconnect(ctx)\nif err != nil && strings.Contains(err.Error(), \"timeout waiting for waiter\") {\n    time.Sleep(3 * time.Second)\n    err = conn.Reconnect(ctx) // retry with backoff\n}","preventionTips":["Add backoff between reconnect attempts after connection drops","Avoid calling Close/Reconnect while another connection operation is known to be running","Track connection state changes so reconnects are not fired during handshakes"],"tags":["wsl","timeout","connection-lifecycle","concurrency"],"backgroundTag":"operation-in-progress","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}