{"record":{"id":"9aa735fefcba1fde","repo":"glanceapp/glance","slug":"parsing-template-w","errorCode":null,"errorMessage":"parsing template: %w","messagePattern":"parsing template: %w","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/widget-custom-api.go","lineNumber":70,"sourceCode":"\twidget.withTitle(\"Custom API\").withCacheDuration(1 * time.Hour)\n\n\tif err := widget.CustomAPIRequest.initialize(); err != nil {\n\t\treturn fmt.Errorf(\"initializing primary request: %v\", err)\n\t}\n\n\tfor key := range widget.Subrequests {\n\t\tif err := widget.Subrequests[key].initialize(); err != nil {\n\t\t\treturn fmt.Errorf(\"initializing subrequest %q: %v\", key, err)\n\t\t}\n\t}\n\n\tif widget.Template == \"\" {\n\t\treturn errors.New(\"template is required\")\n\t}\n\n\tcompiledTemplate, err := template.New(\"\").Funcs(customAPITemplateFuncs).Parse(widget.Template)\n\tif err != nil {\n\t\treturn fmt.Errorf(\"parsing template: %w\", err)\n\t}\n\n\twidget.compiledTemplate = compiledTemplate\n\n\treturn nil\n}\n\nfunc (widget *customAPIWidget) update(ctx context.Context) {\n\tcompiledHTML, err := fetchAndRenderCustomAPIRequest(\n\t\twidget.CustomAPIRequest, widget.Subrequests, widget.Options, widget.compiledTemplate,\n\t)\n\tif !widget.canContinueUpdateAfterHandlingErr(err) {\n\t\treturn\n\t}\n\n\twidget.CompiledHTML = compiledHTML\n}\n","sourceCodeStart":52,"sourceCodeEnd":88,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/widget-custom-api.go#L52-L88","documentation":"Returned by customAPIWidget.initialize when template.New(\"\").Funcs(customAPITemplateFuncs).Parse(widget.Template) fails, i.e. the widget's template string is syntactically invalid Go template text. This is a parse-time error, distinct from execution errors: the template never compiled.","triggerScenarios":"Unclosed action {{ .Foo without }}, unmatched {{if}}/{{end}} or {{range}}/{{end}}, invalid pipeline syntax like {{ .A | }}, or a malformed function call.","commonSituations":"Hand-editing the template block in YAML; YAML stripping or mangling braces due to quoting/indentation; copying a template that uses different delimiters; truncation by a multiline block scalar mistake (| vs >).","solutions":["Check the wrapped parse error: text/template reports the offending line/column of the template string.","Balance every {{if}}/{{range}}/{{with}} with {{end}} and close every {{ }} action.","In YAML use a literal block (template: |) with consistent indentation so braces survive parsing.","Paste the template into a Go playground with template.New(\"t\").Parse to validate syntax quickly."],"exampleFix":"# before\ntemplate: >-\n  {{ if .JSON.hello }} hello {{ end  -- missing brace\n\n# after\ntemplate: >-\n  {{ if .JSON.hello }}hello{{ end }}","handlingStrategy":"validation","validationCode":"// pre-parse templates in CI or a config check\n_, err := template.New(\"\").Funcs(customAPITemplateFuncs).Parse(cfg.Template)\nif err != nil {\n    return fmt.Errorf(\"custom-api template does not parse: %w\", err)\n}","typeGuard":null,"tryCatchPattern":"compiled, err := template.New(\"\").Funcs(customAPITemplateFuncs).Parse(tpl)\nif err != nil {\n    return fmt.Errorf(\"parsing template: %w\", err) // parse error = config bug, do not retry\n}","preventionTips":["Use YAML literal blocks (template: |) for multiline templates.","Balance {{if}}/{{range}}/{{with}} with {{end}}; count them before saving.","Validate templates in a Go playground snippet or CI step before deploy."],"tags":["template","config","custom-api","widget"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}