gohugoio/hugo · error
ErrShutdown
ErrShutdown
Error message
dispatcher is shutting down
What it means
ErrShutdown (internal/warpc/warpc.go:201) is returned by the warpc dispatcher pool when a call is attempted or in flight while the pool of WASM worker processes (used for katex, AVIF, WebP, etc.) is being closed. It signals that the RPC layer is tearing down, not that the request itself was invalid.
Source
Thrown at internal/warpc/warpc.go:201
stdout io.WriteCloser
stdoutBinary hugio.ReadWriteCloser
dec *json.Decoder
enc *json.Encoder
}
func (p *inOut) Close() error {
if err := p.stdin.Close(); err != nil {
return err
}
// This will also close the underlying writers.
if err := p.stdout.Close(); err != nil {
return err
}
return nil
}
var ErrShutdown = fmt.Errorf("dispatcher is shutting down")
var timerPool = sync.Pool{}
func getTimer(d time.Duration) *time.Timer {
if v := timerPool.Get(); v != nil {
timer := v.(*time.Timer)
timer.Reset(d)
return timer
}
return time.NewTimer(d)
}
func putTimer(t *time.Timer) {
if !t.Stop() {
select {
case <-t.C:
default:
}View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Scroll up in the log for the first error — an earlier WASM module failure usually closed the pool; fix that root cause.
- If it only occurs on interrupt/shutdown, it's benign; ignore it.
- Re-run the build; if it reproduces cleanly, upgrade Hugo and report the sequence of errors.
Defensive patterns
Strategy: type-guard
Type guard
func isShutdown(err error) bool { return errors.Is(err, warpc.ErrShutdown) } Try / catch
res, err := d.Execute(ctx, msg)
if errors.Is(err, warpc.ErrShutdown) {
// dispatcher closed (build teardown) — stop submitting work, do not retry
return err
} Prevention
- Check errors.Is(err, ErrShutdown) and treat it as a signal to stop, not a transient failure
- Order teardown so no goroutine submits calls after Close()
- Tie call submission to the same context that governs dispatcher lifetime
When it happens
Trigger: dispatcherPool.Execute or send() racing with pool Close() — e.g. image/katex rendering still running while Hugo shuts down, a fatal error in one dispatcher triggering pool teardown, or a server rebuild closing the pool mid-render.
Common situations: Ctrl-C or build abort while templates are still rendering math/images; a preceding WASM module crash (look for earlier errors in the log — this one is often the secondary symptom); very long builds where an earlier fatal dispatcher error closed the pool.
Related errors
- received invalid image dimensions: %dx%d stride %d
- decoded AVIF buffer size %d is not a multiple of frame size
- timeout
- received response for unknown call ID %d: WASM module violat
- errConfigNotSet
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/83900b20b7e03027.json.
Report an issue: GitHub ↗.