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

  1. Inspect the wrapped panic value (%v) in the error message to find the root cause
  2. Add nil-checks and bounds checks in the create function before dereferencing
  3. 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

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


AI-assisted analysis of gohugoio/hugo@52c9bd7908 (2026-08-09). Data as JSON: /api/errors/3dcb11246f9340f9. Report an issue: GitHub.