Measured while implementing #5321 on origin/main @ f2158ec86. Filed unassigned, not claimed, and deliberately not fixed there — #5321 owns the missing tree KEY in the same map, and this is a different defect (a key that is present but whose VALUE no longer resolves), needing new icon names chosen rather than a key added.
What was measured
ViewSwitcher.resolveIcon (packages/plugin-view/src/ViewSwitcher.tsx) turns an icon NAME into a component by PascalCasing it and looking it up in lucide's icons record:
const iconName = toPascalCase(name);
const mapped = iconNameMap[iconName] || iconName;
return (icons as any)[mapped] || null;
Two of the names ObjectView's iconMap supplies do not exist in that record on the installed lucide-react@1.31.0. Probed directly against the installed package:
kanban kanban -> Kanban RESOLVES
calendar calendar -> Calendar RESOLVES
map map -> Map RESOLVES
gallery layout-grid -> LayoutGrid RESOLVES
timeline activity -> Activity RESOLVES
gantt gantt-chart -> GanttChart *** MISSING ***
grid table -> Table RESOLVES
list list -> List RESOLVES
detail file-text -> FileText RESOLVES
chart bar-chart-3 -> BarChart3 *** MISSING ***
tree list-tree -> ListTree RESOLVES
The cause is that lucide keeps the old spellings as deprecated NAMED EXPORTS while dropping them from the icons record that a by-name lookup reads. Measured on the same version:
| name | named export | in icons |
|---|
BarChart3 | yes | no |
GanttChart | yes | no |
GanttChartSquare | yes | no |
ChartColumn | yes | yes |
ChartGantt | yes | yes |
So the compiler is no help here: ViewSwitcher.tsx imports BarChart3 and GanttChartSquare by name for its own DEFAULT_VIEW_ICONS and type-checks clean, while the by-name path beside it silently misses.
User-visible effect
getViewIcon does not fall back to DEFAULT_VIEW_ICONS once an explicit icon is set — it returns resolveIcon(view.icon), i.e. null:
function getViewIcon(view: ViewSwitcherItem): LucideIcon | null {
if (view.icon) {
return resolveIcon(view.icon);
}
return DEFAULT_VIEW_ICONS[view.type] || null;
}
and the render site is {Icon ? ( Icon ) : null}. ObjectView always supplies an icon string (icon: iconMap[v.type] || 'table'), so a host-composed chart or gantt view is drawn as a label with no icon at all, while every other type in the same switcher has one. No crash. The console reaches this: CreateViewDialog offers both chart and gantt among the view types a user can create, and those records arrive as ObjectView's views prop.
Why it is worth a card rather than a drive-by
Picking the replacements is a judgement call, not a mechanical rename — lucide offers several candidates per glyph (ChartColumn, ChartColumnBig, ChartGantt, ChartNoAxesGantt), and the choice should probably be made together with the DEFAULT_VIEW_ICONS entries beside them, which still import the deprecated aliases. There is also a guard question worth settling in the same breath: nothing today fails when a name stops resolving, which is exactly why this survived a major lucide bump. A pin asserting that every name the map supplies resolves in icons would close the class; #5321 deliberately left its resolvability assertion scoped to tree alone and says so in a comment, so that the widening happens here with the fix rather than as a surprise red.
Not fixed in #5321
#5321's ruling was about which view types are authorable, and its one behaviour change was adding the missing tree KEY (tree: 'list-tree', verified resolving). Its scope fence is packages/plugin-view/src/** plus the record; changing two working-looking icon names on a judgement call is outside it.
Dedup
Searched open issues for the lucide-name shape, for the iconMap / view-switcher icon shape, and for lucide upgrade cards. Nothing open covers it. Related and closed: #2916 (added the chart key to this same map — the key it added is the one now failing to resolve), #1885 (tree view added). Related and open: #5321 (the missing tree key, and the host-only view-type record).
Measured while implementing #5321 on
origin/main@f2158ec86. Filed unassigned, not claimed, and deliberately not fixed there — #5321 owns the missingtreeKEY in the same map, and this is a different defect (a key that is present but whose VALUE no longer resolves), needing new icon names chosen rather than a key added.What was measured
ViewSwitcher.resolveIcon(packages/plugin-view/src/ViewSwitcher.tsx) turns an icon NAME into a component by PascalCasing it and looking it up in lucide'siconsrecord:Two of the names
ObjectView'siconMapsupplies do not exist in that record on the installedlucide-react@1.31.0. Probed directly against the installed package:The cause is that lucide keeps the old spellings as deprecated NAMED EXPORTS while dropping them from the
iconsrecord that a by-name lookup reads. Measured on the same version:iconsBarChart3GanttChartGanttChartSquareChartColumnChartGanttSo the compiler is no help here:
ViewSwitcher.tsximportsBarChart3andGanttChartSquareby name for its ownDEFAULT_VIEW_ICONSand type-checks clean, while the by-name path beside it silently misses.User-visible effect
getViewIcondoes not fall back toDEFAULT_VIEW_ICONSonce an expliciticonis set — it returnsresolveIcon(view.icon), i.e.null:and the render site is
{Icon ? ( Icon ) : null}.ObjectViewalways supplies an icon string (icon: iconMap[v.type] || 'table'), so a host-composedchartorganttview is drawn as a label with no icon at all, while every other type in the same switcher has one. No crash. The console reaches this:CreateViewDialogoffers bothchartandganttamong the view types a user can create, and those records arrive asObjectView'sviewsprop.Why it is worth a card rather than a drive-by
Picking the replacements is a judgement call, not a mechanical rename — lucide offers several candidates per glyph (
ChartColumn,ChartColumnBig,ChartGantt,ChartNoAxesGantt), and the choice should probably be made together with theDEFAULT_VIEW_ICONSentries beside them, which still import the deprecated aliases. There is also a guard question worth settling in the same breath: nothing today fails when a name stops resolving, which is exactly why this survived a major lucide bump. A pin asserting that every name the map supplies resolves iniconswould close the class; #5321 deliberately left its resolvability assertion scoped totreealone and says so in a comment, so that the widening happens here with the fix rather than as a surprise red.Not fixed in #5321
#5321's ruling was about which view types are authorable, and its one behaviour change was adding the missing
treeKEY (tree: 'list-tree', verified resolving). Its scope fence ispackages/plugin-view/src/**plus the record; changing two working-looking icon names on a judgement call is outside it.Dedup
Searched open issues for the lucide-name shape, for the
iconMap/ view-switcher icon shape, and for lucide upgrade cards. Nothing open covers it. Related and closed: #2916 (added thechartkey to this same map — the key it added is the one now failing to resolve), #1885 (tree view added). Related and open: #5321 (the missingtreekey, and the host-only view-type record).