{"record":{"id":"63739b7d1a97cc6e","repo":"actualbudget/actual","slug":"invalid-date","errorCode":null,"errorMessage":"Invalid date: ","messagePattern":"Invalid date: ","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/aql/schema-helpers.ts","lineNumber":30,"sourceCode":"  if (value === undefined) {\n    throw new Error('Query value cannot be undefined');\n  } else if (value === null) {\n    if (type === 'boolean') {\n      return 0;\n    }\n\n    return null;\n  }\n\n  switch (type) {\n    case 'date':\n      if (value instanceof Date) {\n        return toDateRepr(dayFromDate(value));\n      } else if (\n        value.match(/^\\d{4}-\\d{2}-\\d{2}$/) == null ||\n        value < '1995-01-01'\n      ) {\n        throw new Error('Invalid date: ' + value);\n      }\n\n      return toDateRepr(value);\n    case 'date-month':\n      return toDateRepr(value.slice(0, 7));\n    case 'date-year':\n      return toDateRepr(value.slice(0, 4));\n    case 'boolean':\n      return value ? 1 : 0;\n    case 'id':\n      if (typeof value !== 'string' && value !== null) {\n        throw new Error('Invalid id, must be string: ' + value);\n      }\n      return value;\n    case 'integer':\n      if (typeof value === 'number' && Number.isInteger(value)) {\n        return value;\n      } else {","sourceCodeStart":12,"sourceCodeEnd":48,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/aql/schema-helpers.ts#L12-L48","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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)."],"exampleFix":"// before\nq('transactions').insert({ date: '2024-06-01T12:00:00Z' });\n// after\nq('transactions').insert({ date: dayFromDate(new Date('2024-06-01T12:00:00Z')) });","handlingStrategy":"validation","validationCode":"const isDayStr = (v) => typeof v === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(v) && v >= '1995-01-01';","typeGuard":"function isQueryDate(v) {\n  if (v instanceof Date) return true;\n  return typeof v === 'string' && /^\\d{4}-\\d{2}-\\d{2}$/.test(v) && v >= '1995-01-01';\n}","tryCatchPattern":"try {\n  return await runQuery(q.filter({ date }));\n} catch (e) {\n  if (e.message.startsWith('Invalid date:')) {\n    logger.warn('Falling back: bad date input', { date });\n    return null;\n  }\n  throw e;\n}","preventionTips":["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"],"tags":["date","validation","aql","format"],"backgroundTag":"invalid-date-format","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}