{"record":{"id":"8ad237e562533764","repo":"gohugoio/hugo","slug":"content-source-failed-to-convert-t-to-string-s","errorCode":null,"errorMessage":"content source: failed to convert %T to string: %s","messagePattern":"content source: failed to convert %T to string: (.+?)","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"critical","filePath":"resources/page/pagemeta/page_frontmatter.go","lineNumber":560,"sourceCode":"\tValue any\n}\n\nfunc (s Source) IsZero() bool {\n\treturn !hreflect.IsTruthful(s.Value)\n}\n\nfunc (s Source) IsResourceValue() bool {\n\t_, ok := s.Value.(resource.Resource)\n\treturn ok\n}\n\nfunc (s Source) ValueAsString() string {\n\tif s.Value == nil {\n\t\treturn \"\"\n\t}\n\tss, err := cast.ToStringE(s.Value)\n\tif err != nil {\n\t\tpanic(fmt.Errorf(\"content source: failed to convert %T to string: %s\", s.Value, err))\n\t}\n\treturn ss\n}\n\nfunc (s Source) ValueAsOpenReadSeekCloser() hugio.OpenReadSeekCloser {\n\tcontent := s.ValueAsString()\n\treturn func() (hugio.ReadSeekCloser, error) {\n\t\treturn hugio.NewReadSeekerNoOpCloserFromString(content), nil\n\t}\n}\n\n// FrontMatterOnlyValues holds values that can only be set via front matter.\ntype FrontMatterOnlyValues struct {\n\tResourcesMeta []map[string]any\n}\n\n// FrontMatterHandler maps front matter into Page fields and .Params.\n// Note that we currently have only extracted the date logic.","sourceCodeStart":542,"sourceCodeEnd":578,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/resources/page/pagemeta/page_frontmatter.go#L542-L578","documentation":"This is NOT a returned error but a PANIC: Source.ValueAsString calls cast.ToStringE on the content Value and panics with this message if conversion fails. It is triggered when a content source value is a type spf13/cast cannot stringify (e.g. a struct, map, or complex number). Because it panics, an unrecovered occurrence crashes the build.","triggerScenarios":"A content adapter or Source.Value is set to a non-stringifiable Go value (struct, map[any]any with nested objects, big.Float, etc.) and code later calls ValueAsString/ValueAsOpenReadSeekCloser to read the content.","commonSituations":"Content adapters passing raw decoded JSON/YAML nested structures straight into Source.Value instead of a string/[]byte/io.Reader. Surfaces as a build crash rather than a graceful error.","solutions":["Always set Source.Value to a string, []byte, or an io.ReadSeeker for content, never a nested struct/map.","Marshal complex data to a string (e.g. json.Marshal) before assigning it to Source.Value.","If consuming Source, wrap the call in a recover() guard to convert the panic into a logged error."],"exampleFix":"// before\nsrc := pagemeta.Source{Value: someStruct}\n// after\nb, _ := json.Marshal(someStruct)\nsrc := pagemeta.Source{Value: string(b)}","handlingStrategy":"validation","validationCode":"switch s.Value.(type) {\ncase nil, string, []byte:\n    // safe\ncinstance:\n    // marshal to string before ValueAsString\n}","typeGuard":"func isStringableContent(v any) bool {\n    switch v.(type) {\n    case nil, string, []byte, fmt.Stringer:\n        return true\n    }\n    return false\n}","tryCatchPattern":"defer func() {\n    if r := recover(); r != nil {\n        err = fmt.Errorf(\"content value not stringable: %v\", r)\n    }\n}()\nstr := src.ValueAsString()","preventionTips":["Set Source.Value to string, []byte, or an io.Reader only.","Marshal structs/maps to JSON/YAML strings before assigning to Source.Value.","Wrap ValueAsString callers in recover() to avoid build crashes."],"tags":["hugo","content-adapter","panic","type-mismatch","content"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}