gohugoio/hugo · error

failed to read page content

Error message

failed to read page content: %w

What it means

Returned by pageparser.ParseFrontMatterAndContent when io.ReadAll fails to consume the provided io.Reader. This wraps the underlying I/O error (e.g. a broken pipe, premature close, or failed network read) with %w so callers can unwrap it. The function reads the entire content stream into memory before lexing front matter, so any read fault anywhere in the stream surfaces here.

Solutions

  1. Verify the io.Reader is fully readable before passing it in (e.g. buffer it with a bytes.Buffer or io.ReadAll upstream and handle errors there).
  2. If reading from a file, check file permissions, that the file is not being written/rotated concurrently, and that it is not truncated.
  3. Unwrap the error with errors.Is/errors.As to distinguish a transient I/O fault from a permanent one and decide whether to retry the read.

Example fix

// before
r := openUnreliableReader()
cf, err := pageparser.ParseFrontMatterAndContent(r)
if err != nil { return err }

// after: buffer first so read errors surface explicitly
buf, err := io.ReadAll(openUnreliableReader())
if err != nil { return fmt.Errorf("prefetch content: %w", err) }
cf, err := pageparser.ParseFrontMatterAndContent(bytes.NewReader(buf))
if err != nil { return err }
Defensive patterns

Strategy: validation

Validate before calling

// Pre-buffer the reader so parse errors are decoupled from read errors.
func safeParse(r io.Reader) (pageparser.ContentFrontMatter, error) {
    b, err := io.ReadAll(r)
    if err != nil {
        return pageparser.ContentFrontMatter{}, fmt.Errorf("prefetch content: %w", err)
    }
    if len(b) == 0 {
        return pageparser.ContentFrontMatter{}, errors.New("empty content input")
    }
    return pageparser.ParseFrontMatterAndContent(bytes.NewReader(b))
}

Try / catch

if cf, err := pageparser.ParseFrontMatterAndContent(r); err != nil {
    var pathErr *fs.PathError
    if errors.As(err, &pathErr) { /* handle file-level fault */ }
    return err
} else { use(cf) }

Prevention

When it happens

Trigger: Calling pageparser.ParseFrontMatterAndContent(r) where r is an io.Reader whose Read returns an error before EOF -- e.g. a bytes.Reader that's fine, but a network-backed reader, a gzip.Reader on truncated data, or a file Reader on a disk that hits an I/O error mid-read.

Common situations: Content served over an unreliable stream, a content file that is concurrently truncated/rotated, a reader wrapping a tar/gzip stream that ends unexpectedly, or a custom io.Reader implementation that returns an error instead of io.EOF.

Related errors


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

Appendix: source

Thrown at parser/pageparser/pageparser.go:63

		return nil, err
	}
	return l.items, l.err
}

type ContentFrontMatter struct {
	Content           []byte
	FrontMatter       map[string]any
	FrontMatterFormat metadecoders.Format
}

// ParseFrontMatterAndContent is a convenience method to extract front matter
// and content from a content page.
func ParseFrontMatterAndContent(r io.Reader) (ContentFrontMatter, error) {
	var cf ContentFrontMatter

	input, err := io.ReadAll(r)
	if err != nil {
		return cf, fmt.Errorf("failed to read page content: %w", err)
	}

	psr, err := ParseBytes(input, Config{})
	if err != nil {
		return cf, err
	}

	var frontMatterSource []byte

	iter := NewIterator(psr)

	walkFn := func(item Item) bool {
		if frontMatterSource != nil {
			// The rest is content.
			cf.Content = input[item.low:]
			// Done
			return false
		} else if item.IsFrontMatter() {

View on GitHub (pinned to 52c9bd7908)