actualbudget/actual · error
Unsupported schedule status for tooltip: ${scheduleStatus}
Error message
Unsupported schedule status for tooltip: ${scheduleStatus} What it means
getScheduleStatusDescription maps a schedule's computed status to a localized tooltip description. The switch over scheduleStatus has cases for the known statuses; the default branch throws when a status value arrives that has no tooltip mapping. This fail-fast keeps unmapped statuses from silently rendering an empty tooltip.
Source
Thrown at packages/desktop-client/src/hooks/useCategoryScheduleGoalTemplateIndicator.ts:152
'Missed {{scheduleName}} due {{distanceFromNow}} ({{formattedDate}})',
{
scheduleName: schedule.name,
distanceFromNow,
formattedDate,
},
);
case 'due':
case 'upcoming':
return t(
'{{scheduleName}} is due {{distanceFromNow}} ({{formattedDate}})',
{
scheduleName: schedule.name,
distanceFromNow: isToday ? t('today') : distanceFromNow,
formattedDate,
},
);
default:
throw new Error(
`Unsupported schedule status for tooltip: ${scheduleStatus}`,
);
}
}
View on GitHub (pinned to d4334cb6e6)
Solutions
- Log the actual scheduleStatus value and confirm it against the statuses handled in useCategoryScheduleGoalTemplateIndicator.ts
- Add a case (or extend the mapping) for the new status in getScheduleStatusDescription
- If it's your own code, pass only statuses produced by the shared schedule-status utility rather than hand-built strings
- Wrap in try/catch and fall back to a generic tooltip text
Example fix
// before
default:
throw new Error(`Unsupported schedule status for tooltip: ${scheduleStatus}`);
// after
default:
return t('Upcoming'); // safe fallback instead of throwing Defensive patterns
Strategy: fallback
Validate before calling
const KNOWN = ['scheduled','missed','completed','todo' /* match hook's statuses */];
if (!KNOWN.includes(scheduleStatus)) return t('Upcoming'); Type guard
type ScheduleStatus = Parameters<typeof getScheduleStatusDescription>[0];
function isScheduleStatus(v: unknown): v is ScheduleStatus {
return typeof v === 'string'; /* narrow against the concrete union in the hook */
} Try / catch
let description: string;
try {
description = getScheduleStatusDescription(status, schedule, t);
} catch (e) {
if (e instanceof Error && e.message.startsWith('Unsupported schedule status')) {
description = t('Upcoming');
} else throw e;
} Prevention
- Derive statuses only from the shared schedule-status utility
- When adding a status to the schedule logic, update the tooltip switch in the same PR
- Exhaustiveness-check the switch with a never-based assert so TS flags missing cases
- Test getScheduleStatusDescription against every status value
When it happens
Trigger: A scheduleStatus value outside the handled set (e.g. 'scheduled', 'missed', or a newly added status) reaches the function — typically when schedule-goal status computation gains a new variant but the tooltip map isn't updated, or custom template code passes an unexpected status string.
Common situations: Version skew: schedules computed by newer loot-core code viewed in an older client; a plugin or custom report reusing the hook with its own status strings; a typo when passing a status manually.
Related errors
- Unknown format type: ${type}
- Unknown locale ${language}
- Schedule not found: ${id}
- Unsupported scheduled frequency: ${frequency}
- Invalid recurring date config
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/e25615da5c074bd1.
Report an issue: GitHub.