amir20/dozzle · info
canceled: with
Error message
canceled: %v with %w
What it means
rpcErrToErr maps gRPC status code Canceled to "canceled: %v with %w", wrapping context.Canceled so callers can use errors.Is(err, context.Canceled). It indicates the RPC was cancelled, typically by the caller's own context or a client disconnect, not a server failure.
Solutions
- Check errors.Is(err, context.Canceled) and log at debug level; it is usually expected during shutdown/navigation
- If cancellations are unexpected, audit who cancels the parent ctx (http request lifecycle, timeout wrappers)
- Do not reconnect on Canceled; only resubscribe on genuine stream failures
- Increase per-request deadlines if intentional timeouts are cutting streams short
Example fix
// before
if err := <-streamErr; err != nil { log.Error().Err(err).Msg("stream error") }
// after
if err := <-streamErr; err != nil {
if errors.Is(err, context.Canceled) { return } // expected on disconnect
log.Error().Err(err).Msg("stream error")
} Defensive patterns
Strategy: try-catch
Try / catch
if err != nil && errors.Is(err, context.Canceled) {
return // expected on client disconnect or shutdown; do not log as error
} Prevention
- Never treat Canceled as a failure; it accompanies normal SSE teardown and shutdown
- Tie stream contexts to request lifetimes so cancellation is deterministic
- Avoid wrapping stream contexts in additional timeouts you do not control
When it happens
Trigger: Streaming calls (StreamEvents, StreamStats, sendLogs, etc.) whose ctx is cancelled: page navigation closing the SSE stream, client-side timeout, or explicit context cancel/shutdown.
Common situations: User closes a browser tab, cancelling the SSE request context; server shutdown cancelling all in-flight streams; a wrapped HTTP handler timing out and cancelling the request context.
Related errors
- EOF error while converting gRPC to error
- failed to parse certificate
- failed to connect to
- deadline exceeded: with
- unknown error: with
AI-assisted analysis of amir20/dozzle@d9463cbe21 (2026-09-07).
Data as JSON: /api/errors/ee0d3a94e931011a.
Report an issue: GitHub.
Appendix: source
Thrown at internal/agent/client.go:123
}
func rpcErrToErr(err error) error {
if err == nil {
return nil
}
status, ok := status.FromError(err)
if !ok {
return err
}
if status.Code() == codes.Unknown && status.Message() == "EOF" {
return fmt.Errorf("EOF error while converting gRPC to error: %w", io.EOF)
}
switch status.Code() {
case codes.Canceled:
return fmt.Errorf("canceled: %v with %w", status.Message(), context.Canceled)
case codes.DeadlineExceeded:
return fmt.Errorf("deadline exceeded: %v with %w", status.Message(), context.DeadlineExceeded)
case codes.Unknown:
return fmt.Errorf("unknown error: %v with %w", status.Message(), err)
case codes.OK:
return nil
default:
return fmt.Errorf("unknown code: %v with %w", status.Code(), err)
}
}
func (c *Client) LogsBetweenDates(ctx context.Context, containerID string, since time.Time, until time.Time, std container.StdType) (<-chan *container.LogEvent, error) {
stream, err := c.client.LogsBetweenDates(ctx, &pb.LogsBetweenDatesRequest{
ContainerId: containerID,
Since: timestamppb.New(since),
Until: timestamppb.New(until),
StreamTypes: int32(std),
})View on GitHub (pinned to d9463cbe21)