gohugoio/hugo · error
panic: %v
Error message
panic: %v
What it means
In dynacache, GetOrCreateWitTimeout runs the value-creation function in a goroutine with a deferred recover (dynacache.go:438-444). If the create callback panics, the recovered value is converted into a fmt.Errorf("panic: %v", r) and returned as a normal error instead of crashing the process. The %v carries the original panic value for diagnosis.
Source
Thrown at cache/dynacache/dynacache.go:443
}
// GetOrCreateWitTimeout gets or creates a value for the given key and times out if the create function
// takes too long.
func (p *Partition[K, V]) doGetOrCreateWitTimeout(key K, duration time.Duration, create func(key K) (V, error)) (V, error) {
resultch := make(chan V, 1)
errch := make(chan error, 1)
go func() {
var (
v V
err error
)
defer func() {
if r := recover(); r != nil {
if rerr, ok := r.(error); ok {
err = rerr
} else {
err = fmt.Errorf("panic: %v", r)
}
}
if err != nil {
errch <- err
} else {
resultch <- v
}
}()
v, _, err = p.c.GetOrCreate(key, create)
}()
select {
case v := <-resultch:
return v, nil
case err := <-errch:
return p.zero, err
case <-time.After(duration):
return p.zero, &herrors.TimeoutError{View on GitHub (pinned to 52c9bd7908)
Solutions
- Inspect the wrapped panic value (%v) in the error message to find the root cause
- Add nil-checks and bounds checks in the create function before dereferencing
- Reproduce by calling the create function directly outside the cache to get a full stack trace
Example fix
// before: create may panic on nil input
v, err := partition.GetOrCreateWitTimeout(key, timeout, func(k K) (V, error) {
return doWork(input), nil // input may be nil
})
// after: guard the create function
v, err := partition.GetOrCreateWitTimeout(key, timeout, func(k K) (V, nilV, error) {
if input == nil {
return zero, errors.New("nil input")
}
return doWork(input), nil
}) Defensive patterns
Strategy: try-catch
Validate before calling
// Validate inputs to the create function before it runs inside the cache goroutine.
if input == nil {
return zero, errors.New("input must not be nil")
} Try / catch
// dynacache already recovers the panic into an error; handle it at the call site.
v, err := partition.GetOrCreateWitTimeout(key, timeout, create)
if err != nil {
if strings.Contains(err.Error(), "panic:") {
// log full stack by reproducing outside the cache
log.Printf("cache create panicked: %v", err)
}
return zero, err
} Prevention
- Never let the create callback panic: add nil/bounds checks for all dereferences
- Unit-test the create function in isolation to get a full stack trace on panic
- Keep create functions small and pure to minimize panic surface area
When it happens
Trigger: The create function passed to a dynacache partition's GetOrCreateWitTimeout panics — e.g. nil-pointer dereference, index out of range, or an explicit panic deep in resource/image processing.
Common situations: Bugs in resource transformation pipelines that panic under edge-case inputs; nil dereferences during concurrent image processing; custom code registered as a cache create callback.
Related errors
- failled to create base cache directory: %s
- cache dir %q contains unresolved placeholders
- %q is not a valid cache name
- failed to decode filecache config: %w
- %q must resolve to an absolute directory
AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09).
Data as JSON: /api/errors/3dcb11246f9340f9.
Report an issue: GitHub.