{"record":{"id":"df6b8004e5d2643c","repo":"wavetermdev/waveterm","slug":"msg-error","errorCode":null,"errorMessage":"msg.error","messagePattern":"msg\\.error","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/app/store/wshrpcutil-base.ts","lineNumber":50,"sourceCode":"    const msgFn = (msg: RpcMessage) => {\n        msgQueue.push(msg);\n        signalFn();\n        // reset signal promise\n        signalPromise = new Promise<void>((resolve) => (signalFn = resolve));\n    };\n    openRpcs.set(reqid, {\n        reqId: reqid,\n        startTs: Date.now(),\n        command: command,\n        msgFn: msgFn,\n    });\n    yield null;\n    try {\n        while (true) {\n            while (msgQueue.length > 0) {\n                const msg = msgQueue.shift()!;\n                if (msg.error != null) {\n                    throw new Error(msg.error);\n                }\n                if (!msg.cont && msg.data == null) {\n                    return;\n                }\n                const shouldTerminate = yield msg.data;\n                if (shouldTerminate) {\n                    sendRpcCancel(reqid);\n                    return;\n                }\n                if (!msg.cont) {\n                    return;\n                }\n            }\n            await signalPromise;\n        }\n    } finally {\n        openRpcs.delete(reqid);\n        if (timeoutId != null) {","sourceCodeStart":32,"sourceCodeEnd":68,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/frontend/app/store/wshrpcutil-base.ts#L32-L68","documentation":"rpcResponseGenerator consumes queued streaming RPC responses; when a message carries an `error` field, it throws that error into the generator's consumer. This propagates a remote-side failure (from the peer that produced the stream) to the local caller awaiting the stream.","triggerScenarios":"An RpcMessage in the streaming response queue has msg.error != null — i.e. the remote endpoint sent an explicit error frame instead of data.","commonSituations":"Remote handler threw while producing stream chunks; permission denial from the server for the requested command; network/protocol error reported mid-stream by the peer.","solutions":["Read the thrown message — it is the remote error text — and fix the root cause on the producing side","Wrap the streaming consumption loop in try/catch to handle remote failures gracefully","Check authentication/permissions if the error indicates denial; retry after correcting the request"],"exampleFix":"// before\nfor await (const chunk of gen) { process(chunk); }\n\n// after\ntry {\n    for await (const chunk of gen) { process(chunk); }\n} catch (e) {\n    console.error(\"stream failed:\", e.message);\n}","handlingStrategy":"try-catch","validationCode":"if (msg?.error != null) {\n    // handle remote error before consuming stream\n    console.error(\"remote rpc error:\", msg.error);\n}","typeGuard":"function isRpcError(msg: RpcMessage): boolean {\n    return msg != null && (msg as any).error != null;\n}","tryCatchPattern":"const gen = rpcResponseHelper...();\ntry {\n    for await (const data of gen) { handle(data); }\n} catch (e) {\n    // e.message is the remote error string\n    reportRemoteError(e.message);\n}","preventionTips":["Always consume streaming RPC responses inside try/catch","Log the remote error text — it identifies the server-side root cause","Check auth/permissions before issuing commands that commonly fail remotely"],"tags":["rpc","streaming","remote-error"],"backgroundTag":"rpc-remote-error","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}