{"record":{"id":"63c1c31c7ca73493","repo":"glanceapp/glance","slug":"widget-type-property-is-empty-or-not-specified","errorCode":null,"errorMessage":"widget 'type' property is empty or not specified","messagePattern":"widget 'type' property is empty or not specified","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/glance/widget.go","lineNumber":22,"sourceCode":"\t\"bytes\"\n\t\"context\"\n\t\"errors\"\n\t\"fmt\"\n\t\"html/template\"\n\t\"log/slog\"\n\t\"math\"\n\t\"net/http\"\n\t\"sync/atomic\"\n\t\"time\"\n\n\t\"gopkg.in/yaml.v3\"\n)\n\nvar widgetIDCounter atomic.Uint64\n\nfunc newWidget(widgetType string) (widget, error) {\n\tif widgetType == \"\" {\n\t\treturn nil, errors.New(\"widget 'type' property is empty or not specified\")\n\t}\n\n\tvar w widget\n\n\tswitch widgetType {\n\tcase \"calendar\":\n\t\tw = &calendarWidget{}\n\tcase \"calendar-legacy\":\n\t\tw = &oldCalendarWidget{}\n\tcase \"clock\":\n\t\tw = &clockWidget{}\n\tcase \"weather\":\n\t\tw = &weatherWidget{}\n\tcase \"bookmarks\":\n\t\tw = &bookmarksWidget{}\n\tcase \"iframe\":\n\t\tw = &iframeWidget{}\n\tcase \"html\":","sourceCodeStart":4,"sourceCodeEnd":40,"githubUrl":"https://github.com/glanceapp/glance/blob/91324e8de762702e97b0ac5c8e36271d644d8642/internal/glance/widget.go#L4-L40","documentation":"Returned by newWidget() in internal/glance/widget.go when a page defines a widget whose 'type' YAML key is missing or set to an empty string. The type string drives the switch that instantiates the correct widget struct; without it Glance cannot construct anything, so page parsing aborts with this error.","triggerScenarios":"A YAML mapping under page.contents (or nested under a widget that proxies others, e.g. group) lacks the type key, has `type:` with no value, or has type: \"\". Also happens when the type key is mis-indented so it lands outside the widget map.","commonSituations":"Copy-pasting a widget snippet and deleting the type line; YAML indentation drift putting type under the wrong nesting level; commenting out type while testing; an empty trailing `-` item in the contents list.","solutions":["Add a valid type: <widget-name> to every item in page contents (e.g. type: bookmarks, type: weather).","Fix indentation so type sits at the same level as the widget's other options.","Remove empty `-` entries from contents lists.","Run `glance config:validate` to get the exact location of the offending widget."],"exampleFix":"# glance.yml (before)\ncontent:\n  - name: Home\n    widgets:\n      -:\n        title: Links\n\n# after\ncontent:\n  - name: Home\n    widgets:\n      - type: bookmarks\n        title: Links","handlingStrategy":"validation","validationCode":"# rough check: every widget item in contents must have a type\npython3 - <<'EOF'\nimport yaml,sys\ncfg=yaml.safe_load(open('glance.yml'))\nfor page in cfg.get('pages',[]):\n    for w in page.get('contents',[]):\n        assert isinstance(w,dict) and w.get('type'), f'missing type in {page.get(\"name\")}: {w}'\nprint('ok')\nEOF","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Start every widget block with its type: line.","Watch YAML indentation when nesting widgets (groups, splitter columns).","Remove leftover empty `-` list items."],"tags":["config","yaml","widget","validation"],"backgroundTag":null,"analyzedSha":"91324e8de762702e97b0ac5c8e36271d644d8642","analyzedAt":"2026-08-15T14:12:54.279Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}