gohugoio/hugo · error

timed out rendering the page content. Extend the `timeout` l

Error message

timed out rendering the page content. Extend the `timeout` limit in your Hugo config file: %w

What it means

Returned from the plain-content computation in page__content.go when rendering a page's content exceeds Hugo's configured build timeout; herrors.IsTimeoutError detects the context timeout and Hugo wraps it with a hint to raise the `timeout` config value (default 30s or 60s depending on version). It exists because content rendering is guarded by a deadline to catch template deadlocks and runaway work.

Source

Thrown at hugolib/page__content.go:825

		// TODO(bep) is set in a test. Fix that.
		if result.fuzzyWordCount == 0 {
			result.fuzzyWordCount = (result.wordCount + 100) / 100 * 100
		}

		if isCJKLanguage {
			result.readingTime = (result.wordCount + 500) / 501
		} else {
			result.readingTime = (result.wordCount + 212) / 213
		}

		rs.Value = result

		return rs, nil
	})
	if err != nil {
		if herrors.IsTimeoutError(err) {
			err = fmt.Errorf("timed out rendering the page content. Extend the `timeout` limit in your Hugo config file: %w", err)
		}
		return contentPlainPlainWords{}, err
	}
	return v.Value, nil
}

type cachedContentScope struct {
	*cachedContent
	pco   *pageContentOutput
	scope string
}

func (c *cachedContentScope) prepareContext(ctx context.Context) context.Context {
	// A regular page's shortcode etc. may be rendered by e.g. the home page,
	// so we need to track any changes to this content's page.
	ctx = tpl.Context.DependencyManagerScopedProvider.Set(ctx, c.pco.po.p)

	// The markup scope is recursive, so if already set to a non zero value, preserve that value.

View on GitHub ↗ (pinned to 8a468df065)

Solutions

  1. First check for self-reference: search layouts for shortcodes/partials/render hooks calling .Page.Content, .Summary, or .WordCount on the page being rendered — that's a deadlock, and raising the timeout won't fix it.
  2. If work is genuinely heavy, raise the limit in hugo.toml: `timeout = '120s'`.
  3. Cache expensive operations: use partialCached, cache remote resources, and pre-process images so repeated builds hit resources/_gen.
  4. On CI, persist the resources/ and cache directories between builds so image processing isn't repeated.

Example fix

# hugo.toml before
# (no timeout set — 30s default)
# after
timeout = '120s'
Defensive patterns

Strategy: retry

Validate before calling

# hugo.toml — size the limit to the heaviest page
timeout = '120s'

Try / catch

if err := h.Build(cfg); err != nil {
    if strings.Contains(err.Error(), "timed out rendering") {
        // raise `timeout` in config or break the recursion, then rebuild
    }
    return err
}

Prevention

When it happens

Trigger: A page whose content rendering takes longer than `timeout`: huge markdown files, expensive shortcodes (resources.GetRemote, image processing of many/large images), or — very commonly — recursive template loops such as a shortcode or render hook calling .Page.Content on the same page, which deadlocks until the timeout fires.

Common situations: Sites with thousands of images processed in shortcodes; slow remote data/resource fetches during render; a partial or render-hook that references .Summary/.Content of the page currently rendering (self-reference deadlock); underpowered CI runners where builds are simply slower.

Related errors


AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31). Data as JSON: /data/errors/3f03c40c102ebdce.json. Report an issue: GitHub ↗.