{"record":{"id":"3bc94dae64caaa35","repo":"wavetermdev/waveterm","slug":"ec-time-timeout-waiting-for-response","errorCode":null,"errorMessage":"EC-TIME: timeout waiting for response","messagePattern":"EC-TIME: timeout waiting for response","errorType":"error_code","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/wshutil/wshrpc.go","lineNumber":405,"sourceCode":"outer:\n\tfor {\n\t\tvar inputVal baseds.RpcInputChType\n\t\tvar inputChMore bool\n\t\tvar resIdTimeout string\n\n\t\tselect {\n\t\tcase inputVal, inputChMore = <-w.InputCh:\n\t\t\tif !inputChMore {\n\t\t\t\tbreak outer\n\t\t\t}\n\t\t\tif w.Debug {\n\t\t\t\tlog.Printf(\"[%s] received message: %s\\n\", w.DebugName, string(inputVal.MsgBytes))\n\t\t\t}\n\t\tcase resIdTimeout = <-w.CtxDoneCh:\n\t\t\tif w.Debug {\n\t\t\t\tlog.Printf(\"[%s] received request timeout: %s\\n\", w.DebugName, resIdTimeout)\n\t\t\t}\n\t\t\tw.unregisterRpc(resIdTimeout, fmt.Errorf(\"EC-TIME: timeout waiting for response\"))\n\t\t\tcontinue\n\t\t}\n\n\t\tvar msg RpcMessage\n\t\terr := json.Unmarshal(inputVal.MsgBytes, &msg)\n\t\tif err != nil {\n\t\t\tlog.Printf(\"wshrpc received bad message: %v\\n\", err)\n\t\t\tcontinue\n\t\t}\n\t\tif msg.Cancel {\n\t\t\tif msg.ReqId != \"\" {\n\t\t\t\tw.cancelRequest(msg.ReqId)\n\t\t\t}\n\t\t\tcontinue\n\t\t}\n\t\tif msg.IsRpcRequest() {\n\t\t\t// Handle stream commands synchronously since the broker is designed to be non-blocking.\n\t\t\t// RecvData/RecvAck just enqueue to work queues, so there's no risk of blocking the main loop.","sourceCodeStart":387,"sourceCodeEnd":423,"githubUrl":"https://github.com/wavetermdev/waveterm/blob/a4447c1563b2df285ab89e76c82f91e1a1a49c1e/pkg/wshutil/wshrpc.go#L387-L423","documentation":"In runServer, when the per-request timeout fires (CtxDoneCh signals the registered response id), the pending RPC is unregistered with this error. The caller of the request (SendComplexRequest/ SendSimpleRequest path) receives \"EC-TIME: timeout waiting for response\" because the remote side never responded within the timeout window.","triggerScenarios":"Calling an RPC whose handler never calls SendResponse/SendResponseError before the configured (or default DefaultTimeoutMs) timeout elapses; remote peer hung, slow, or connection dead; the noTimeout/streaming request not being used for long operations.","commonSituations":"Long-running commands (heavy terminal/file ops) exceeding the default timeout; a blocked remote block controller; network disconnect leaving the request pending; calling an RPC route that no one serves.","solutions":["Increase the timeout via the request options (or use a noTimeout/streaming variant) for long-running commands.","Ensure the server-side handler always responds, including error paths (SendResponseError).","Verify the route/target exists and is alive; check connection state between the two endpoints.","Add debug logging (EnableRpcDebug) on both ends to see whether the request was received and processed.","Retry the request after checking the peer is responsive."],"exampleFix":"// before\nresp, err := w.SendComplexRequest(\"longop\", args, &wshutil.RpcOpts{Route: route})\n// after\nresp, err := w.SendComplexRequest(\"longop\", args, &wshutil.RpcOpts{Route: route, TimeoutMs: 60000})","handlingStrategy":"try-catch","validationCode":"if w == nil || !w.IsServerDone() == false {\n    return fmt.Errorf(\"rpc server already shut down, skipping request\")\n}","typeGuard":"func peerAlive(w *wshutil.WshRpc) bool {\n    return w != nil && !w.IsServerDone()\n}","tryCatchPattern":"handler, err := w.SendComplexRequest(cmd, args, &wshutil.RpcOpts{Route: route, TimeoutMs: 30000})\nif err != nil {\n    if strings.Contains(err.Error(), \"EC-TIME\") {\n        // increase timeout or check remote handler responsiveness, then retry once\n    }\n    return err\n}","preventionTips":["Set explicit TimeoutMs for long-running commands instead of relying on the default.","Ensure every server handler responds on all paths, including errors (SendResponseError).","Monitor connection health; a dead peer guarantees client timeouts.","Use debug logging (EnableRpcDebug) to trace request/response round trips when timeouts appear."],"tags":["rpc","timeout","no-response"],"backgroundTag":"rpc-timeout-waiting-for-response","analyzedSha":"a4447c1563b2df285ab89e76c82f91e1a1a49c1e","analyzedAt":"2026-09-01T15:26:23.972Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}