actualbudget/actual · error
Invalid date:
Error message
Invalid date:
What it means
For `date`-typed columns, convertInputType accepts only a Date object or a strict `YYYY-MM-DD` string that is also >= 1995-01-01. Anything else (malformed strings, timestamps, month-only strings) is rejected with 'Invalid date: <value>'. This protects the day-based date storage representation (toDateRepr) from invalid input.
Source
Thrown at packages/loot-core/src/server/aql/schema-helpers.ts:30
if (value === undefined) {
throw new Error('Query value cannot be undefined');
} else if (value === null) {
if (type === 'boolean') {
return 0;
}
return null;
}
switch (type) {
case 'date':
if (value instanceof Date) {
return toDateRepr(dayFromDate(value));
} else if (
value.match(/^\d{4}-\d{2}-\d{2}$/) == null ||
value < '1995-01-01'
) {
throw new Error('Invalid date: ' + value);
}
return toDateRepr(value);
case 'date-month':
return toDateRepr(value.slice(0, 7));
case 'date-year':
return toDateRepr(value.slice(0, 4));
case 'boolean':
return value ? 1 : 0;
case 'id':
if (typeof value !== 'string' && value !== null) {
throw new Error('Invalid id, must be string: ' + value);
}
return value;
case 'integer':
if (typeof value === 'number' && Number.isInteger(value)) {
return value;
} else {View on GitHub (pinned to d4334cb6e6)
Solutions
- Normalize the value to a YYYY-MM-DD day string before querying (e.g. slice an ISO timestamp: iso.slice(0, 10)).
- Use the shared `dayFromDate` util to convert a Date object instead of formatting by hand.
- Use the `date-month` or `date-year` field types if you actually have coarser-grained dates.
- Check for dates earlier than 1995-01-01 and handle them explicitly (clamp or reject in your own code).
Example fix
// before
q('transactions').insert({ date: '2024-06-01T12:00:00Z' });
// after
q('transactions').insert({ date: dayFromDate(new Date('2024-06-01T12:00:00Z')) }); Defensive patterns
Strategy: validation
Validate before calling
const isDayStr = (v) => typeof v === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(v) && v >= '1995-01-01'; Type guard
function isQueryDate(v) {
if (v instanceof Date) return true;
return typeof v === 'string' && /^\d{4}-\d{2}-\d{2}$/.test(v) && v >= '1995-01-01';
} Try / catch
try {
return await runQuery(q.filter({ date }));
} catch (e) {
if (e.message.startsWith('Invalid date:')) {
logger.warn('Falling back: bad date input', { date });
return null;
}
throw e;
} Prevention
- Always normalize timestamps with dayFromDate or slice(0, 10) before storing
- Use the date-month/date-year field types for coarser dates
- Reject dates before 1995-01-01 in your import pipeline
When it happens
Trigger: Passing a full ISO timestamp ('2024-01-01T10:00:00Z'), a numeric epoch, an empty string, a 'YYYY-MM' string into a `date` field, or a valid-format date earlier than 1995-01-01 into an aql query param.
Common situations: Feeding values from third-party APIs (full ISO timestamps) directly into transactions.date, using Date.now() output instead of formatted day strings, or importing historical data predating 1995.
Related errors
- Bad ${type} format: ${str}
- Invalid cutoff date: expected a valid date (e.g. YYYY-MM-DD)
- Casting string fields to dates is not supported
- Query value cannot be undefined
- Invalid id, must be string:
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/63739b7d1a97cc6e.
Report an issue: GitHub.