{"record":{"id":"44b2b70b0be72bb3","repo":"gohugoio/hugo","slug":"type-t-not-supported-44b2b7","errorCode":null,"errorMessage":"type %T not supported","messagePattern":"type %T not supported","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"tpl/transform/unmarshal.go","lineNumber":121,"sourceCode":"\n\t\t\treturn &resources.StaleValue[any]{\n\t\t\t\tValue: v,\n\t\t\t\tStaleVersionFunc: func() uint32 {\n\t\t\t\t\treturn resource.StaleVersion(r)\n\t\t\t\t},\n\t\t\t}, nil\n\t\t})\n\t\tif err != nil {\n\t\t\treturn nil, err\n\t\t}\n\n\t\treturn v.Value, nil\n\n\t}\n\n\tdataStr, err := types.ToStringE(data)\n\tif err != nil {\n\t\treturn nil, fmt.Errorf(\"type %T not supported\", data)\n\t}\n\n\tif strings.TrimSpace(dataStr) == \"\" {\n\t\treturn nil, nil\n\t}\n\n\tkey := hashing.XxHashFromStringHexEncoded(dataStr)\n\n\tif decoder != metadecoders.Default {\n\t\tkey += decoder.OptionsKey()\n\t}\n\n\tv, err := ns.cacheUnmarshal.GetOrCreate(key, func(string) (*resources.StaleValue[any], error) {\n\t\tvar f metadecoders.Format\n\t\tif decoder.Format != \"\" {\n\t\t\tf = metadecoders.FormatFromString(decoder.Format)\n\t\t\tif f == \"\" {\n\t\t\t\treturn nil, fmt.Errorf(\"format %q not supported\", decoder.Format)","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/tpl/transform/unmarshal.go#L103-L139","documentation":"Thrown by transform.Unmarshal (tpl/transform/unmarshal.go:121) in the non-Resource code path after types.ToStringE(data) fails. Unmarshal only accepts data that is a string, []byte, json.RawMessage, or an UnmarshableResource; any other Go type reaches this branch. The %T prints the offending concrete type so the developer can see exactly what was passed.","triggerScenarios":"Calling {{ transform.Unmarshal $value }} (or the Go Namespace.Unmarshal) where $value is an int, bool, struct, map, or slice that is neither string-convertible nor a resource.UnmarshableResource. Common: piping a .Param that resolves to a number or array, or an .Scratch value holding a non-string type.","commonSituations":"Passing already-decoded data (a map from a data file) back into Unmarshal; piping a resource object that does not implement UnmarshableResource; passing front-matter values of unknown type straight from .Params.","solutions":["Coerce the value to a string before unmarshaling: {{ transform.Unmarshal (string $value) }}","Pass a Resource obtained via resources.Get / .Resources instead of a raw value","If the value is already a map/slice, use it directly instead of re-unmarshaling","In Go, assert resource.UnmarshableResource or string/[]byte before calling ns.Unmarshal"],"exampleFix":"// before\n{{ transform.Unmarshal $param }}\n// after\n{{ transform.Unmarshal (string $param) }}","handlingStrategy":"validation","validationCode":"// In Go: check the data type before calling Unmarshal.\nswitch v := data.(type) {\ncase string, []byte, json.RawMessage:\n    // safe\nresource.UnmarshableResource:\n    // safe\ndefault:\n    s, err := types.ToStringE(v)\n    if err != nil {\n        return fmt.Errorf(\"convert data to string before Unmarshal: %w\", err)\n    }\n    data = s\n}\n// In templates: {{ transform.Unmarshal (string $value) }}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always stringify non-resource values before transform.Unmarshal","Prefer passing a Resource over raw values for typed data","Use printf \"%T\" to log the type when debugging template data flow"],"tags":["template","transform","unmarshal","type-conversion"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}