{"record":{"id":"2e7137500d956bc1","repo":"glanceapp/glance","slug":"s-widget-v","errorCode":null,"errorMessage":"%s widget: %v","messagePattern":"(.+?) widget: (.+?)","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/config.go","lineNumber":237,"sourceCode":"\t\t}\n\n\t\tif !filepath.IsAbs(filePath) {\n\t\t\treturn \"\", false, fmt.Errorf(\"readFileFromEnv: file path %s is not absolute\", filePath)\n\t\t}\n\n\t\tfileContents, err := os.ReadFile(filePath)\n\t\tif err != nil {\n\t\t\treturn \"\", false, fmt.Errorf(\"readFileFromEnv: reading file from %s: %v\", variableName, err)\n\t\t}\n\n\t\treturn strings.TrimSpace(string(fileContents)), false, nil\n\tdefault:\n\t\treturn \"\", true, nil\n\t}\n}\n\nfunc formatWidgetInitError(err error, w widget) error {\n\treturn fmt.Errorf(\"%s widget: %v\", w.GetType(), err)\n}\n\nvar configIncludePattern = regexp.MustCompile(`(?m)^([ \\t]*)(?:-[ \\t]*)?(?:!|\\$)include:[ \\t]*(.+)$`)\n\nfunc parseYAMLIncludes(mainFilePath string) ([]byte, map[string]struct{}, error) {\n\treturn recursiveParseYAMLIncludes(mainFilePath, nil, 0)\n}\n\nfunc recursiveParseYAMLIncludes(mainFilePath string, includes map[string]struct{}, depth int) ([]byte, map[string]struct{}, error) {\n\tif depth > CONFIG_INCLUDE_RECURSION_DEPTH_LIMIT {\n\t\treturn nil, nil, fmt.Errorf(\"recursion depth limit of %d reached\", CONFIG_INCLUDE_RECURSION_DEPTH_LIMIT)\n\t}\n\n\tmainFileContents, err := os.ReadFile(mainFilePath)\n\tif err != nil {\n\t\treturn nil, nil, fmt.Errorf(\"reading %s: %w\", mainFilePath, err)\n\t}\n","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/config.go#L219-L255","documentation":"This error wraps any failure that occurs while a widget defined in the glance configuration is being initialized. formatWidgetInitError prefixes the widget's type (from w.GetType()) to the underlying error so the user knows which widget in the YAML failed. It is not an error condition itself; the root cause is always the wrapped error after the colon.","triggerScenarios":"Glance parses a page's widgets, constructs each widget by type (e.g. feed via type: feed), and the widget's constructor returns an error — for example a required field missing (feed without feed-url), an invalid URL, or an unparsable option. The wrapper fires during config parse/apply at startup or on config hot-reload.","commonSituations":"A typo in a widget field name, forgetting a mandatory option like feed-url, putting a widget's settings under the wrong nesting level, or upgrading glance so a widget option changed its expected format. On config reload this makes the offending widget render as an error card or abort the reload.","solutions":["Read the text after 'widget:' — it names the exact widget type and the underlying cause; fix that field in glance.yml","Compare the widget's YAML block against the widget's documentation for required options","If the error mentions a URL or parse failure, verify the value's format (scheme, escaping of colons in YAML)","After a version upgrade, check the changelog for renamed/removed widget options"],"exampleFix":"# before\ntype: feed\nwidgets:\n  - type: feed\n# after (missing option added)\ntype: feed\nwidgets:\n  - type: feed\n    feed-url: https://example.com/rss","handlingStrategy":"try-catch","validationCode":"// Before applying config, dry-parse it and report per-widget errors:\nif _, err := glance.ParseAndValidateConfig(bytes); err != nil {\n    log.Printf(\"config rejected: %v\", err)\n}","typeGuard":null,"tryCatchPattern":"err := cfg.Apply()\nif err != nil {\n    if strings.HasSuffix(err.Error(), \"widget\") || strings.Contains(err.Error(), \" widget: \") {\n        // extract widget type from prefix, underlying cause from suffix\n        log.Printf(\"widget init failed: %v\", err)\n    }\n    return err\n}","preventionTips":["Validate config in CI with a parse step before deploying","Use glance's config check / hot-reload to surface widget errors without downtime","Keep widget blocks minimal and copied from current docs"],"tags":["glance","widget","configuration","yaml"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}