{"record":{"id":"42efab78b3f169fa","repo":"gohugoio/hugo","slug":"invalid-text-font-source-t","errorCode":null,"errorMessage":"invalid text font source: %T","messagePattern":"invalid text font source: %T","errorType":"panic","errorClass":null,"httpStatus":null,"severity":"error","filePath":"resources/images/filters.go","lineNumber":122,"sourceCode":"\t\t\t\t\tpanic(\"alignx must be one of left, center, right\")\n\t\t\t\t}\n\t\t\tcase \"aligny\":\n\t\t\t\ttf.aligny = cast.ToString(v)\n\t\t\t\tif tf.aligny != \"top\" && tf.aligny != \"center\" && tf.aligny != \"bottom\" {\n\t\t\t\t\tpanic(\"aligny must be one of top, center, bottom\")\n\t\t\t\t}\n\n\t\t\tcase \"linespacing\":\n\t\t\t\ttf.linespacing = cast.ToInt(v)\n\t\t\tcase \"font\":\n\t\t\t\tif err, ok := v.(error); ok {\n\t\t\t\t\tpanic(fmt.Sprintf(\"invalid font source: %s\", err))\n\t\t\t\t}\n\t\t\t\tfontSource, ok1 := v.(hugio.ReadSeekCloserProvider)\n\t\t\t\tidentifier, ok2 := v.(resource.Identifier)\n\n\t\t\t\tif !(ok1 && ok2) {\n\t\t\t\t\tpanic(fmt.Sprintf(\"invalid text font source: %T\", v))\n\t\t\t\t}\n\n\t\t\t\ttf.fontSource = fontSource\n\n\t\t\t\t// The input value isn't hashable and will not make a stable key.\n\t\t\t\t// Replace it with a string in the map used as basis for the\n\t\t\t\t// hash string.\n\t\t\t\topt[\"font\"] = identifier.Key()\n\n\t\t\t}\n\t\t}\n\t}\n\n\treturn filter{\n\t\tOptions: newFilterOpts(text, opt),\n\t\tFilter:  tf,\n\t}\n}","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/gohugoio/hugo/blob/52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2/resources/images/filters.go#L104-L140","documentation":"Thrown by images.Text when the `font` option is not an error but also does not satisfy both required interfaces: hugio.ReadSeekCloserProvider (provides a readable font stream) and resource.Identifier (provides a stable cache key) — see filters.go:118-123. The panic prints the concrete Go type (%T) that was supplied.","triggerScenarios":"Passing a plain string path, a []byte of font data, an os.File, or any object that is not a Hugo resource as the `font` value. Only Hugo resource objects that expose both interfaces qualify.","commonSituations":"Developer passes a filesystem path string instead of resources.Get result; passes a remote bytes blob; or passes a resource of a non-font media type that still lacks the required interfaces.","solutions":["Load the font via resources.Get (assets/) or resources.GetRemote and pass that resource object as `font`.","Confirm the resource is non-nil and not an error before use.","Do not pass raw strings, []byte, or file handles directly."],"exampleFix":"// before\n{{ $filters = $filters | append (images.Text \"Hi\" (dict \"font\" \"assets/fonts/Fira.woff\")) }}\n// after\n{{ $font := resources.Get \"fonts/Fira.woff\" }}\n{{ $filters = $filters | append (images.Text \"Hi\" (dict \"font\" $font)) }}","handlingStrategy":"type-guard","validationCode":"{{ with resources.Get \"fonts/Fira.woff\" }}\n  {{ $filters = $filters | append (images.Text \"Hi\" (dict \"font\" .)) }}\n{{ else }}\n  {{ errorf \"font resource not found\" }}\n{{ end }}","typeGuard":"// IsFontResource checks the Hugo resource satisfies both interfaces Text requires.\nfunc IsFontResource(v any) bool {\n    _, a := v.(hugio.ReadSeekCloserProvider)\n    _, b := v.(resource.Identifier)\n    return a && b\n}","tryCatchPattern":null,"preventionTips":["Always obtain fonts via resources.Get/GetRemote, never pass raw strings or bytes.","Confirm the resource is non-nil before use.","Keep font assets under assets/ and reference them by that path."],"tags":["image-filter","text-rendering","font","type-mismatch","hugo"],"backgroundTag":null,"analyzedSha":"52c9bd7908b4d02d4d0ff8f82a888834d6ee10d2","analyzedAt":"2026-08-09T21:49:36.660Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}