laurent22/joplin · error · Error
Unsupported folder icon type
Error message
Unsupported folder icon type: ${icon.type} What it means
SidebarIcon renders a folder icon based on icon.type; it supports Emoji, DataUrl, and FontAwesome types. If the icon object's type property holds any other value, the component throws this Error rather than rendering a broken icon. It is an exhaustive-branch guard over the FolderIconType enum.
Solutions
- Add a rendering branch (or map the unknown value onto a default icon) for the missing FolderIconType in SidebarIcon.tsx
- Normalize legacy icon data on load: map or strip icons whose type is no longer in FolderIconType
- Validate the icon object with a type guard before rendering and fall back to a default icon
- Log the offending icon.type value to identify which data/enum version produced it
Example fix
// before
} else {
throw new Error(`Unsupported folder icon type: ${icon.type}`);
}
// after
} else if (icon.type === FolderIconType.NewType) {
return <NewIconComponent .../>;
} else {
return <Icon style={[styles.baseTextIcon, styles.fontIcon, style]} name="far fa-folder" accessibilityLabel={null}/>;
} Defensive patterns
Strategy: validation
Validate before calling
const RENDERABLE_ICON_TYPES = [FolderIconType.Emoji, FolderIconType.DataUrl, FolderIconType.FontAwesome]; const isRenderableIcon = (icon: any) => icon && RENDERABLE_ICON_TYPES.includes(icon.type);
Type guard
const isFolderIcon = (v: unknown): v is FolderIcon => !!v && typeof v === 'object' && 'type' in v && [FolderIconType.Emoji, FolderIconType.DataUrl, FolderIconType.FontAwesome].includes((v as FolderIcon).type);
Try / catch
let content;
try {
content = <SidebarIcon icon={icon}/>;
} catch (e) {
console.warn('Falling back to default folder icon:', e);
content = <Icon name="far fa-folder" accessibilityLabel={null}/>;
} Prevention
- Wrap unknown-icon rendering in a type guard and render a default folder icon as fallback
- Normalize icon data on load/import: drop or remap records whose type is not in FolderIconType
- When adding a FolderIconType value, update SidebarIcon's branch chain in the same commit
- Keep legacy enum values migrated during app-version upgrades so persisted data never carries stale types
When it happens
Trigger: Passing an icon whose type is not one of FolderIconType.Emoji/DataUrl/FontAwesome — e.g. an old persisted icon record with a removed enum value, a typo like 'fontawesome' as a raw string, a new FolderIconType added without updating SidebarIcon, or icon being undefined/garbage data.
Common situations: Migrating or syncing notes between app versions where the icon enum changed; user-edited or imported data containing an unknown type value; adding a new FolderIconType case in the enum but forgetting the renderer branch in SidebarIcon.tsx.
Related errors
AI-assisted analysis of laurent22/joplin@981a03c5c9 (2026-09-17).
Data as JSON: /api/errors/9ff5460c4bfa2154.
Report an issue: GitHub.
Appendix: source
Thrown at packages/app-mobile/components/SideMenuContent/SidebarIcon.tsx:33
return <View style={styles.emptyIcon}/>;
}
if (typeof icon === 'string') {
icon = {
type: FolderIconType.FontAwesome,
name: icon,
emoji: '',
dataUrl: '',
};
}
if (icon.type === FolderIconType.Emoji) {
return <Text style={[styles.baseTextIcon, styles.emojiIcon, style]}>{icon.emoji}</Text>;
} else if (icon.type === FolderIconType.DataUrl) {
return <Image style={[styles.imageIcon, style]} source={{ uri: icon.dataUrl }}/>;
} else if (icon.type === FolderIconType.FontAwesome) {
return <Icon style={[styles.baseTextIcon, styles.fontIcon, style]} name={icon.name} accessibilityLabel={null}/>;
} else {
throw new Error(`Unsupported folder icon type: ${icon.type}`);
}
};
const iconWidth = 20;
const styles = StyleSheet.create({
baseTextIcon: {
textAlign: 'center',
textAlignVertical: 'center',
minWidth: iconWidth,
},
imageIcon: {
height: 20,
resizeMode: 'contain',
width: iconWidth,
},
fontIcon: {
fontSize: 18,
},View on GitHub (pinned to 981a03c5c9)