actualbudget/actual · error · CompileError
Casting string fields to dates is not supported
Error message
Casting string fields to dates is not supported
What it means
castInput (compiler.ts:264) can auto-cast only literal strings into dates. If the expression is a non-literal string (e.g. a string column/field reference), the compiler cannot convert it at compile time, so it throws this CompileError — string fields must be transformed explicitly, not implicitly cast.
Source
Thrown at packages/loot-core/src/server/aql/compiler.ts:269
return typed(expr.value, type);
} else if (expr.type === 'null') {
if (!expr.literal) {
throw new CompileError("A non-literal null doesn't make sense");
}
if (type === 'boolean') {
return typed(0, 'boolean', { literal: true });
}
return expr;
}
// These are all things that can be safely casted automatically
if (type === 'date') {
if (expr.type === 'string') {
if (expr.literal) {
return parseDate(expr.value) || badDateFormat(expr.value, 'date');
} else {
throw new CompileError(
'Casting string fields to dates is not supported',
);
}
}
throw new CompileError(`Can't cast ${expr.type} to date`);
} else if (type === 'date-month') {
let expr2;
if (expr.type === 'date') {
expr2 = expr;
} else if (expr.type === 'string' || expr.type === 'any') {
expr2 =
parseMonth(expr.value) ||
parseDate(expr.value) ||
badDateFormat(expr.value, 'date-month');
} else {
throw new CompileError(`Can't cast ${expr.type} to date-month`);
}View on GitHub (pinned to d4334cb6e6)
Solutions
- Use $transform with $date/$datemachine-style functions to explicitly convert the string field before date comparison.
- Ensure the value being compared is a literal date string (auto-parsed) or a genuine date field, not a raw string column.
- If the column holds machine dates, compare it as a string/date-machinable value rather than forcing a date cast.
Example fix
// before
.filter({ imported_date: { $gte: '2024-01-01' } }) // imported_date is a string field in a date op
// after
.transform({ imported_date: { $date: '$imported_date' } })
.filter({ imported_date: { $gte: '2024-01-01' } }) Defensive patterns
Strategy: validation
Validate before calling
function assertDateComparable(expr) {
// only literal strings or date-typed fields may take part in date comparisons
if (expr.kind === 'field' && expr.type === 'string') {
throw new Error('Convert string field with $transform/$date before date comparison');
}
} Type guard
function isDateTyped(fieldDesc) {
return fieldDesc != null && (fieldDesc.type === 'date' || String(fieldDesc.type).startsWith('date-'));
} Try / catch
try {
runQuery(q);
} catch (e) {
if (e.message.includes('Casting string fields to dates is not supported')) {
throw new Error('Transform the string field to a date explicitly first');
} else throw e;
} Prevention
- Only compare date-typed fields or literal date strings in date operations
- Use $transform date conversions for string columns
- Check field types in the AQL schema before writing comparisons
When it happens
Trigger: Comparing a string field to a date in a filter where the string side is a field reference rather than a literal, e.g. building expressions where a non-literal string expr is used where a date type is required.
Common situations: Queries comparing two columns of mismatched types (string field vs date field); custom rules/reports referencing string columns inside date functions; migration of queries after type checking tightened.
Related errors
- Bad ${type} format: ${str}
- Field "${field}" does not exist in table "${tableName}"
- Invalid path: ${path}
- Path error: ${tableName} table does not exist
- Field not joinable on table ${tableName}: "${field}"
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/680997289d1c1893.
Report an issue: GitHub.