gohugoio/hugo · error
content source: failed to convert %T to string: %s
Error message
content source: failed to convert %T to string: %s
What it means
`Source.ValueAsString` in page_frontmatter.go casts the front matter `content.value` to a string with `cast.ToStringE` and **panics** with this message when the value is not string-convertible. It's a panic, not a returned error, because callers such as `ValueAsOpenReadSeekCloser` treat the content as already-validated. The `%T` shows the actual Go type Hugo received from the decoded front matter.
Source
Thrown at resources/page/pagemeta/page_frontmatter.go:560
Value any
}
func (s Source) IsZero() bool {
return !hreflect.IsTruthful(s.Value)
}
func (s Source) IsResourceValue() bool {
_, ok := s.Value.(resource.Resource)
return ok
}
func (s Source) ValueAsString() string {
if s.Value == nil {
return ""
}
ss, err := cast.ToStringE(s.Value)
if err != nil {
panic(fmt.Errorf("content source: failed to convert %T to string: %s", s.Value, err))
}
return ss
}
func (s Source) ValueAsOpenReadSeekCloser() hugio.OpenReadSeekCloser {
content := s.ValueAsString()
return func() (hugio.ReadSeekCloser, error) {
return hugio.NewReadSeekerNoOpCloserFromString(content), nil
}
}
// FrontMatterOnlyValues holds values that can only be set via front matter.
type FrontMatterOnlyValues struct {
ResourcesMeta []map[string]any
}
// FrontMatterHandler maps front matter into Page fields and .Params.
// Note that we currently have only extracted the date logic.View on GitHub ↗ (pinned to 8a468df065)
Solutions
- Make `content.value` a scalar string — use a YAML block scalar (`value: |`) or TOML multi-line `"""` literal instead of a nested structure.
- Check the reported `%T` in the panic: `map[string]interface {}` or `[]interface {}` means the front matter parsed as a structure, so fix the indentation/quoting.
- If you meant to reference an existing resource, assign the resource object itself so `IsResourceValue` matches, rather than a wrapper map.
- Reproduce with a minimal page and `hugo --logLevel debug` to identify which page's front matter carries the bad value.
Example fix
# before — YAML parses as a map, panics
resources:
- name: intro
content:
value:
title: Hello
# after — scalar string
resources:
- name: intro
content:
value: |
title: Hello Defensive patterns
Strategy: type-guard
Type guard
// ensure content source value is a string (or fmt.Stringer) before assigning
func isStringable(v any) bool {
switch v.(type) {
case string, fmt.Stringer, []byte:
return true
}
return false
} Prevention
- In content adapters, pass content.value as a string, not a map/slice/number
- Convert non-string values explicitly (e.g. with printf/string) before setting page content
- Validate the shape of externally-sourced data (JSON APIs) before feeding it to AddPage
When it happens
Trigger: Setting a page resource's `content.value` to a map, slice/array, or arbitrary struct instead of a scalar — e.g. a YAML block that parses as a nested mapping or a list — and then having Hugo read that resource's content (via `.Content`, `.ReadSeekCloser`, or publishing it).
Common situations: YAML indentation errors that turn an intended multi-line string into a nested map or sequence; TOML arrays used for multi-line content; passing a `resource.Resource` or a template-produced dict into `content.value` when a literal string was intended (note `IsResourceValue` handles genuine Resource values, so this panic means an unsupported third type).
Related errors
- media type %q not found
- failed to create resource for path %q, expected a resource.R
- failed to convert %T to a string slice
- error processing file %q
- failed to parse file %q: %s
AI-assisted analysis of gohugoio/hugo@8a468df065 (2026-07-31).
Data as JSON: /data/errors/8ad237e562533764.json.
Report an issue: GitHub ↗.