wavetermdev/waveterm · warning
timeout sending cancel
Error message
timeout sending cancel
What it means
SendCancelResponse writes a cancel acknowledgment to the RPC output channel; if the surrounding context is done before the write is accepted, the handler is finalized and this error is returned. It indicates the cancel notification itself could not be delivered in time.
Source
Thrown at pkg/wshutil/wshrpc.go:573
return handler.ctx
}
func (handler *RpcRequestHandler) SendCancel(ctx context.Context) error {
defer func() {
panichandler.PanicHandler("SendCancel", recover())
}()
msg := &RpcMessage{
Cancel: true,
ReqId: handler.reqId,
}
barr, _ := json.Marshal(msg) // will never fail
select {
case handler.w.OutputCh <- barr:
handler.finalize()
return nil
case <-ctx.Done():
handler.finalize()
return fmt.Errorf("timeout sending cancel")
}
}
func (handler *RpcRequestHandler) ResponseDone() bool {
if handler.cachedResp != nil {
return false
}
select {
case msg, more := <-handler.respCh:
if !more {
return true
}
handler.cachedResp = msg
return false
default:
return false
}
}View on GitHub (pinned to a4447c1563)
Solutions
- Check ctx.Err() before calling SendCancelResponse; skip the cancel send if the context is already done.
- Ensure the connection reader keeps draining OutputCh so the cancel message can be written.
- Treat this error as benign during shutdown (the handler was finalized either way) and log at debug level instead of retrying.
Example fix
// before
err := handler.SendCancelResponse(ctx)
// after
if ctx.Err() == nil {
err := handler.SendCancelResponse(ctx)
} Defensive patterns
Strategy: try-catch
Validate before calling
if ctx.Err() != nil {
return nil // cancel notification cannot be delivered
} Try / catch
if err := handler.SendCancelResponse(ctx); err != nil && strings.Contains(err.Error(), "timeout sending cancel") {
// context already done; handler finalized — safe to ignore/log at debug level
} Prevention
- Check ctx.Err() before sending cancel responses.
- Keep the output channel drained so writes are not blocked.
- Treat cancel-send failures during shutdown as benign.
- Avoid cancel calls with already-expired deadlines.
When it happens
Trigger: Calling SendCancelResponse after the request context was already cancelled/expired; OutputCh backpressure (downstream not consuming) combined with a closing/shut-down context.
Common situations: Cancelling a request while the connection is being torn down; caller cancels with an already-expired deadline; slow consumer blocking OutputCh during shutdown.
Understand the failure class
- Timeouts: ETIMEDOUT, deadlines, and hung requests — what actually expires when a request times out.
Related errors
- failed to list workspaces: %v
- failed to list blocks from all %d workspace(s)
- reinstalling connection: %w
- disconnecting %q error: %w
- ensuring connection: %w
AI-assisted analysis of wavetermdev/waveterm@a4447c1563 (2026-09-01).
Data as JSON: /api/errors/fe1bd9eeb7f09977.
Report an issue: GitHub.