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
- Use a long-lived context (not request-scoped or already-cancelled) for Refresh
- Check ctx.Err() before calling Refresh and skip if cancelled
- 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
- Pass a process-lifetime context to Refresh, never a request context
- Do not Refresh concurrently with Shutdown
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
- duplicated values: %v
- unmarshalling json data into aghalg.NullBool: bad value %q
- json duration is nil
- unknown cipher %q
- parsing tls certificate: %w
AI-assisted analysis of AdguardTeam/AdGuardHome@b41aefbe51 (2026-08-27).
Data as JSON: /api/errors/886a2e11800fb766.
Report an issue: GitHub.