AdguardTeam/AdGuardHome · info

refreshing: %w

Error message

refreshing: %w

What it means

Refresh signals the TLS manager that configuration changed by pushing to its updates channel; this error occurs only when the passed context is cancelled before the non-blocking send succeeds (or immediately). It wraps context.Canceled or context.DeadlineExceeded.

Source

Thrown at internal/aghtls/defaultmanager.go:247

	}

	err := mgr.watcher.Add(p)
	if err != nil {
		errs = append(errs, fmt.Errorf("watching %s %s: %w", what, p, err))
	}

	return errs
}

// Refresh implements the [service.Refresher] interface for *DefaultManager.
func (mgr *DefaultManager) Refresh(ctx context.Context) (err error) {
	mgr.logger.DebugContext(ctx, "refreshing")

	select {
	case mgr.updates <- UpdateSignal{}:
		return nil
	case <-ctx.Done():
		return fmt.Errorf("refreshing: %w", ctx.Err())
	default:
		return nil
	}
}

// Start implements the [service.Interface] interface for *DefaultManager.
func (mgr *DefaultManager) Start(ctx context.Context) (err error) {
	err = mgr.watcher.Start(ctx)
	if err != nil {
		return fmt.Errorf("starting watcher: %w", err)
	}

	go mgr.handleEvents(ctx)
	go mgr.handleCertFileChange(ctx)

	return nil
}

View on GitHub (pinned to b41aefbe51)

Solutions

  1. Use a long-lived context (not request-scoped or already-cancelled) for Refresh
  2. Check ctx.Err() before calling Refresh and skip if cancelled
  3. Retry Refresh after shutdown completes on a fresh manager instance

Example fix

// before
mgr.Refresh(reqCtx) // reqCtx may already be cancelled
// after
if err := mgr.Refresh(longLivedCtx); err != nil { /* log, non-fatal */ }
Defensive patterns

Strategy: try-catch

Validate before calling

if ctx.Err() != nil {
    return ctx.Err()
}

Try / catch

if err := mgr.Refresh(ctx); err != nil {
    if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
        return // benign during shutdown
    }
    return err
}

Prevention

When it happens

Trigger: Calling mgr.Refresh(ctx) with an already-cancelled context or one whose deadline expires at the same moment the updates channel is full, so the ctx.Done() branch wins the select.

Common situations: Calling Refresh during shutdown when the root context is already cancelled; Refreshing from a request-scoped context that times out; concurrent Refresh calls racing with Shutdown closing the updates channel.

Related errors


AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27). Data as JSON: /api/errors/886a2e11800fb766. Report an issue: GitHub.