t8y2/dbx · error · errXuguOperationTimeout

%w after %ds

Error message

%w after %ds

What it means

The clean timeout variant: the operation timed out after timeoutSecs but the waiter itself produced no additional error, so the driver returns a wrapped errXuguOperationTimeout ('xugu operation timed out') with only the duration. The %w wrapping lets callers match with errors.Is(err, errXuguOperationTimeout).

Source

Thrown at agents/drivers/xugu/main.go:4322

	if s.activeTimer != nil {
		s.activeTimer.Stop()
		s.activeTimer = nil
	}
	timedOut := s.activeTimedOut
	canceled := s.activeCanceled
	s.activeTimedOut = false
	s.activeCanceled = false
	s.activeCancelMu.Unlock()
	cancel()
	return xuguOperationResultError(timedOut, canceled, timeoutSecs, operationErr)
}

func xuguOperationResultError(timedOut, canceled bool, timeoutSecs int, operationErr error) error {
	if timedOut {
		if operationErr != nil {
			return fmt.Errorf("%w after %ds: %v", errXuguOperationTimeout, timeoutSecs, operationErr)
		}
		return fmt.Errorf("%w after %ds", errXuguOperationTimeout, timeoutSecs)
	}
	if canceled {
		if operationErr != nil {
			return fmt.Errorf("%w: %v", errXuguOperationCanceled, operationErr)
		}
		return errXuguOperationCanceled
	}
	return operationErr
}

func (s *server) cancelActiveQuery() {
	s.activeCancelMu.Lock()
	cancels := make([]context.CancelFunc, 0, len(s.activeRows)+1)
	if s.activeCancel != nil {
		if !s.activeTimedOut {
			s.activeCanceled = true
			// Explicit cancellation won the race. Disable the watchdog so a
			// slow driver return cannot relabel this operation as a timeout.

View on GitHub (pinned to c0390bff16)

Solutions

  1. Increase timeoutSecs to a value appropriate for the statement's expected duration.
  2. Profile and optimize the slow SQL (indexes, statistics, partitions).
  3. Run long operations asynchronously or in the background instead of under a short wait.
  4. Retry during off-peak windows if the timeout is load-related.

Example fix

// before
rows, err := q.Run(sql, 10) // times out after 10s on big scan

// after
rows, err := q.Run(sql, 120)
Defensive patterns

Strategy: retry

Validate before calling

// ensure the timeout budget covers worst-case plan
explain, _ := db.Query("EXPLAIN " + sql)
// compare estimated rows against timeout heuristic before executing

Try / catch

if errors.Is(err, errXuguOperationTimeout) {
    return retryWithLargerTimeout(op, timeoutSecs*2)
}

Prevention

When it happens

Trigger: A monitored operation's elapsed time exceeded timeoutSecs and the result channel/poll returned normally, indicating pure timeout without a secondary failure.

Common situations: Queries exceeding a deliberately short timeout; batch jobs hitting a fixed timeout budget; server under load causing slow but healthy operations.

Related errors


AI-assisted analysis of t8y2/dbx@c0390bff16 (2026-09-05). Data as JSON: /api/errors/b4cfe14e420aec8f. Report an issue: GitHub.