wavetermdev/waveterm · error
server is no longer running, cannot send new requests
Error message
server is no longer running, cannot send new requests
What it means
WshRpc refuses to send new requests once its server has been marked done (IsServerDone). This guards against writing onto a dead/closed connection and fails fast instead of hanging on a response that will never arrive.
Source
Thrown at pkg/wshutil/wshrpc.go:765
func (handler *RpcResponseHandler) Finalize() {
// Always unregister the handler from the map, even if already done
if handler.reqId != "" {
handler.w.unregisterResponseHandler(handler.reqId)
}
if handler.done.Load() {
return
}
// SendResponse with done=true will call close() via defer, even when reqId is empty
handler.SendResponse(nil, true)
}
func (handler *RpcResponseHandler) IsDone() bool {
return handler.done.Load()
}
func (w *WshRpc) SendComplexRequest(command string, data any, opts *wshrpc.RpcOpts) (rtnHandler *RpcRequestHandler, rtnErr error) {
if w.IsServerDone() {
return nil, errors.New("server is no longer running, cannot send new requests")
}
if opts == nil {
opts = &wshrpc.RpcOpts{}
}
timeoutMs := opts.Timeout
if timeoutMs <= 0 {
timeoutMs = DefaultTimeoutMs
}
defer func() {
panichandler.PanicHandler("SendComplexRequest", recover())
}()
if command == "" {
return nil, fmt.Errorf("command cannot be empty")
}
handler := &RpcRequestHandler{
w: w,
ctxCancelFn: &atomic.Pointer[context.CancelFunc]{},
}View on GitHub (pinned to a4447c1563)
Solutions
- Check w.IsServerDone() (or connection state) before sending; skip or re-establish the connection first.
- Recreate the client/connection and retry the request after reconnecting.
- Restructure code so all RPCs complete before shutdown, or cancel in-flight work at teardown.
- Add a guard in your wrapper that converts this error into a reconnect-and-retry flow.
- Avoid holding WshRpc references beyond the owning component's lifetime.
Example fix
// before
resp, err := wshobj.SendComplexRequestTimeOut(ctx, "wave:info", opts, 3000) // panics-style hard error after close
// after
if wshobj.IsServerDone() {
return fmt.Errorf("connection closed, skipping request")
}
resp, err := wshobj.SendComplexRequestTimeOut(ctx, "wave:info", opts, 3000) Defensive patterns
Strategy: validation
Validate before calling
if w.IsServerDone() {
return fmt.Errorf("skipping %s: server closed", command)
} Try / catch
hdl, err := w.SendComplexRequest(command, data, opts)
if err != nil && strings.Contains(err.Error(), "server is no longer running") {
w = reconnect(); hdl, err = w.SendComplexRequest(command, data, opts)
} Prevention
- Gate all sends on IsServerDone()/connection-alive checks.
- Stop background senders during shutdown before closing the server.
- Recreate WshRpc clients after connection loss instead of reusing them.
- Scope client references to the owning component's lifetime.
When it happens
Trigger: Calling w.SendComplexRequest (or wrappers like SendRpc/SendComplexRequestTimeOut) after the WshRpc instance's server side has been shut down/closed (done flag set, e.g. connection teardown or process exit).
Common situations: Issuing commands from a goroutine while the terminal/block connection closes; calling wsh clients after app shutdown; long-lived background tasks outliving their connection.
Related errors
- nil wshrpc passed to wshclient
- no default route
- response channel closed
- <resp.Error>
- no route id available
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/bb7104aeea8a801c.
Report an issue: GitHub.