{"record":{"id":"ebeb8ca2890a1f6f","repo":"wavetermdev/waveterm","slug":"source-cannot-be-blank","errorCode":null,"errorMessage":"source cannot be blank","messagePattern":"source cannot be blank","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"frontend/app/view/term/term-wsh.tsx","lineNumber":29,"sourceCode":"import { isBlank } from \"@/util/util\";\nimport debug from \"debug\";\n\nconst dlog = debug(\"wave:vdom\");\n\nexport class TermWshClient extends WshClient {\n    blockId: string;\n    model: TermViewModel;\n\n    constructor(blockId: string, model: TermViewModel) {\n        super(makeFeBlockRouteId(blockId));\n        this.blockId = blockId;\n        this.model = model;\n    }\n\n    async handle_vdomcreatecontext(rh: RpcResponseHelper, data: VDomCreateContext) {\n        const source = rh.getSource();\n        if (isBlank(source)) {\n            throw new Error(\"source cannot be blank\");\n        }\n        console.log(\"vdom-create\", source, data);\n        const tabId = globalStore.get(atoms.staticTabId);\n        if (data.target?.newblock) {\n            const oref = await RpcApi.CreateBlockCommand(this, {\n                tabid: tabId,\n                blockdef: {\n                    meta: {\n                        view: \"vdom\",\n                        \"vdom:route\": rh.getSource(),\n                    },\n                },\n                magnified: data.target?.magnified,\n                focused: true,\n            });\n            return oref;\n        } else if (data.target?.toolbar?.toolbar) {\n            const oldVDomBlockId = globalStore.get(this.model.vdomToolbarBlockId);","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/frontend/app/view/term/term-wsh.tsx#L11-L47","documentation":"The term-wsh backend handler for vdomcreatecontext requires every RPC request to carry a non-blank source identifier identifying which block/origin sent it. rh.getSource() returning blank means the caller did not attach a source, so the handler refuses to proceed rather than routing output to an unknown destination.","triggerScenarios":"Invoking the VDomCreateContext RPC from a context with no source block set — e.g. a client constructed without a blockId/route context, a test harness, or an RPC issued before block registration so getSource() returns \"\"/null.","commonSituations":"Calling CreateBlock/VDOM commands from shared/global code outside a block controller, refactors that changed how RpcResponseHelper is constructed, or wsh calls issued from a non-block context.","solutions":["Ensure the RPC is issued from a BlockController/attached context so rh.getSource() resolves to a valid block id.","Check how the RpcResponseHelper is constructed and that its source field is populated.","If calling programmatically, pass an explicit source/blockid in the request.","Guard the caller: verify the source is non-blank before dispatching the RPC."],"exampleFix":"// before\nawait RpcApi.VDomCreateContext(globalEnv, data); // no source context\n// after\nconst source = getBlockSource();\nif (isBlank(source)) throw new Error(\"vdomcreatecontext requires a source block\");\nawait RpcApi.VDomCreateContext(makeHelper(source), data);","handlingStrategy":"try-catch","validationCode":"const source = getRpcSource(); // however the client resolves its block source\nif (isBlank(source)) {\n  throw new Error(\"cannot call VDomCreateContext: no source block attached\");\n}\nawait RpcApi.VDomCreateContext(helper, data);","typeGuard":"function hasValidSource(rh: RpcResponseHelper): boolean {\n  return !isBlank(rh.getSource());\n}","tryCatchPattern":"try {\n  await RpcApi.VDomCreateContext(this, data);\n} catch (e) {\n  if (String(e.message) === \"source cannot be blank\") {\n    console.error(\"RPC dispatched without a source block; check block/controller context\");\n    return;\n  }\n  throw e;\n}","preventionTips":["Always issue block-scoped RPCs from a BlockController or context that carries a source id.","Assert the source is set when constructing RpcResponseHelpers in tests/harnesses.","Avoid calling block RPCs from global/shared code paths."],"tags":["rpc","wsh","missing-source"],"backgroundTag":"missing-rpc-source","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}