{"record":{"id":"3888f3704173cab6","repo":"wavetermdev/waveterm","slug":"rpc-error-v","errorCode":null,"errorMessage":"RPC error: %v","messagePattern":"RPC error: (.+?)","errorType":"http","errorClass":null,"httpStatus":500,"severity":"error","filePath":"pkg/web/webvdomproto.go","lineNumber":82,"sourceCode":"\t\tURL:     path,\n\t\tHeaders: headers,\n\t\tBody:    body,\n\t}\n\n\t// Get RPC client\n\tclient := wshserver.GetMainRpcClient()\n\n\t// Make RPC call with route to specific process\n\troute := wshutil.MakeProcRouteId(uuid)\n\trespCh := wshclient.VDomUrlRequestCommand(client, data, &wshrpc.RpcOpts{\n\t\tRoute: route,\n\t})\n\n\t// Handle first response to set headers\n\tfirstResp := true\n\tfor respUnion := range respCh {\n\t\tif respUnion.Error != nil {\n\t\t\thttp.Error(w, fmt.Sprintf(\"RPC error: %v\", respUnion.Error), http.StatusInternalServerError)\n\t\t\treturn\n\t\t}\n\n\t\tresp := respUnion.Response\n\t\tif firstResp {\n\t\t\tfirstResp = false\n\t\t\t// Set status code and headers from first response\n\t\t\tif resp.StatusCode > 0 {\n\t\t\t\tw.WriteHeader(resp.StatusCode)\n\t\t\t} else {\n\t\t\t\tw.WriteHeader(http.StatusOK)\n\t\t\t}\n\t\t\t// Copy headers\n\t\t\tfor key, value := range resp.Headers {\n\t\t\t\tw.Header().Set(key, value)\n\t\t\t}\n\t\t}\n","sourceCodeStart":64,"sourceCodeEnd":100,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/web/webvdomproto.go#L64-L100","documentation":"After proxying the HTTP request over the wsh RPC to the target process, handleVDom streams responses; if any response union carries an Error, pkg/web/webvdomproto.go:82 returns HTTP 500 with 'RPC error: <err>'. It means the remote VDom handler (in the block's process, routed via MakeProcRouteId(uuid)) failed or the RPC could not be delivered.","triggerScenarios":"The target UUID does not correspond to a live block/process (no subscriber on the route), the remote VDomUrlRequest handler returns an error, or the RPC channel closes with an error (timeout, connection to the wave process lost).","commonSituations":"Hitting /vdom/ with a UUID for a block that was closed or crashed, the Wave terminal app not running so the main RPC client has no route, stale bookmarked vdom URLs pointing at dead blocks.","solutions":["Read the wrapped RPC error in the response body — 'route not found'/timeout means the target process is gone.","Verify the block (UUID) still exists and is running; reopen the block and use its current UUID.","Confirm the Wave app / target process is running and the main RPC client is connected.","Retry after the remote process restarts; the route is re-registered when the block is recreated."],"exampleFix":"// before: stale cached block id\nawait fetch(`/vdom/${cachedBlockId}/state`)\n\n// after: refresh the live block id first\nconst liveId = await getActiveBlockId()\nawait fetch(`/vdom/${liveId}/state`)","handlingStrategy":"validation","validationCode":"// ensure the target block/process is live before proxying\nconst live = await isBlockActive(uuid); // via app state / block registry\nif (!live) throw new Error(`vdom target ${uuid} is not running`);","typeGuard":"function isVdomResp(u) {\n  return u != null && (\"Response\" in u || \"Error\" in u);\n}","tryCatchPattern":"const resp = await fetch(`/vdom/${uuid}/render`);\nif (resp.status === 500) {\n  const msg = await resp.text();\n  if (msg.includes(\"RPC error\")) {\n    // target process likely gone: refresh block id and retry once\n    return retryWithFreshBlockId();\n  }\n  throw new Error(msg);\n}","preventionTips":["Resolve the current live block UUID at request time instead of caching it.","Handle route-not-found/timeouts as 'target process closed' and refresh the id.","Keep the Wave app/process running before issuing vdom proxy requests."],"tags":["go","rpc","http","routing"],"backgroundTag":"rpc-call-failed","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}