actualbudget/actual · error · CompileError
Can't cast ${expr.type} to date-year
Error message
Can't cast ${expr.type} to date-year What it means
castInput needs a `date-year` value (YYYY). Accepted sources are `date`, `date-month`, `string`, `any`, params, and null; other types throw with the source type named. Strings are parsed via parseYear/parseMonth/parseDate, and date fields are truncated with SQL SUBSTR.
Source
Thrown at packages/loot-core/src/server/aql/compiler.ts:312
);
} else {
return typed(
`CAST(SUBSTR(${expr2.value}, 1, 6) AS integer)`,
'date-month',
);
}
} else if (type === 'date-year') {
let expr2;
if (expr.type === 'date' || expr.type === 'date-month') {
expr2 = expr;
} else if (expr.type === 'string') {
expr2 =
parseYear(expr.value) ||
parseMonth(expr.value) ||
parseDate(expr.value) ||
badDateFormat(expr.value, 'date-year');
} else {
throw new CompileError(`Can't cast ${expr.type} to date-year`);
}
if (expr2.literal) {
return typed(dateToInt(expr2.value.toString().slice(0, 4)), 'date-year', {
literal: true,
});
} else {
return typed(
`CAST(SUBSTR(${expr2.value}, 1, 4) AS integer)`,
'date-year',
);
}
} else if (type === 'id') {
if (expr.type === 'string') {
return typed(expr.value, 'id', { literal: expr.literal });
}
} else if (type === 'float') {
if (expr.type === 'integer') {View on GitHub (pinned to d4334cb6e6)
Solutions
- Pass a date field or a string like '2024' / '2024-01' / '2024-01-15'
- Confirm the referenced field is the `date` column
- Convert the year to a string before passing it into the query
- Rebuild the filter using { $year: { $field: 'date' } }
Example fix
// before
q.filter({ $year: { $field: 'amount' } })
// after
q.filter({ $year: { $field: 'date' } }) Defensive patterns
Strategy: validation
Validate before calling
const YEAR_RE = /^(\d{4}(-\d{2}(-\d{2})?)?)$/;
if (!(typeof v === 'string' && YEAR_RE.test(v))) {
throw new Error('Expected YYYY (or YYYY-MM-DD) string');
} Type guard
function isYearLike(v) {
return typeof v === 'string' && /^\d{4}(-\d{2}(-\d{2})?)?$/.test(v);
} Try / catch
try {
runQuery(q.filter({ $year: { $field: field } }));
} catch (e) {
if (/Can't cast .* to date-year/.test(e.message)) {
throw new Error(`Field '${field}' cannot be cast to a year`, { cause: e });
}
throw e;
} Prevention
- Pass date/date-month fields or year strings into $year
- Don't pass raw numbers (2024) where a year string/expression is expected
- Verify the field reference points to `date`
When it happens
Trigger: Using a year function/filter with an expression typed integer, float, boolean, id, array, etc. — anything that is not date/date-month/string/any.
Common situations: Yearly summary queries that accidentally reference a numeric column (amount, balance) instead of `date`; programmatic query builders that pass numbers for years into the wrong slot.
Related errors
- Can't cast ${expr.type} to date
- Can't cast ${expr.type} to date-month
- Can't convert ${expr.type} to ${type}
- Table "${tableName}" does not exist in the schema
- Too few arguments
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/2c3f81e86252298c.
Report an issue: GitHub.