actualbudget/actual · error
`date` is required when adding a transaction
Error message
`date` is required when adding a transaction
What it means
normalizeTransactions validates each incoming transaction before inserting it, because the sync code does date manipulation that requires a value. If a transaction has date == null (missing, undefined, or explicit null), the whole batch is rejected with this error before any writes. The db layer would validate too, but this early check gives a clearer message.
Source
Thrown at packages/loot-core/src/server/accounts/sync.ts:452
}
async function normalizeTransactions(
transactions,
acctId,
{
payeeNameNormalization = 'title-case',
}: {
payeeNameNormalization?: PayeeNameNormalization;
} = {},
) {
const payeesToCreate = new Map();
const normalized = [];
for (let trans of transactions) {
// Validate the date because we do some stuff with it. The db
// layer does better validation, but this will give nicer errors
if (trans.date == null) {
throw new Error('`date` is required when adding a transaction');
}
// Strip off the irregular properties
const { payee_name: originalPayeeName, subtransactions, ...rest } = trans;
trans = rest;
if (trans.amount != null && !Number.isInteger(trans.amount)) {
throw new TransactionError(
`Amount is invalid, must be an integer: ${trans.amount}`,
);
}
if (subtransactions) {
for (const sub of subtransactions) {
if (sub.amount != null && !Number.isInteger(sub.amount)) {
throw new TransactionError(
`Subtransaction amount is invalid, must be an integer: ${sub.amount}`,
);View on GitHub (pinned to d4334cb6e6)
Solutions
- Ensure every transaction has a `date` set to a valid date string (e.g. '2024-05-01').
- Default missing dates upstream (e.g. to the statement date) instead of passing null.
- Filter out or reject dateless rows before calling the API and report them.
- Validate the whole batch client-side before submission.
Example fix
// before
await actual.importTransactions(accId, [
{ amount: -2500, payee_name: 'Kroger' } // no date
]);
// after
await actual.importTransactions(accId, [
{ date: '2024-05-01', amount: -2500, payee_name: 'Kroger' }
]); Defensive patterns
Strategy: validation
Validate before calling
const invalid = txs.filter(t => t.date == null);
if (invalid.length) {
throw new Error(`All transactions need a date; ${invalid.length} are missing one`);
} Type guard
function hasDate(t: { date?: string | null }): t is { date: string } {
return t.date != null && t.date.length > 0;
} Try / catch
try {
await importTransactions(accountId, txs);
} catch (e) {
if (e instanceof Error && e.message.includes('`date` is required')) {
console.error('A transaction in the batch is missing a date; check your import mapping');
return;
}
throw e;
} Prevention
- Validate every record's date before calling the API, not per-transaction after failure.
- Default missing dates to a sensible value (e.g. statement date) in import scripts.
- Check CSV/OFX column mapping so the date column populates `date`.
- Handle unparseable dates at parse time instead of passing null through.
When it happens
Trigger: Calling importTransactions/addTransactions (API or internal sync) with a transaction lacking a `date` field — e.g. { amount: -2500, payee_name: 'Kroger' } with no date key, or date explicitly null.
Common situations: CSV/OFX import scripts that fail to map a date column; API integrations building transactions from partial records with empty source dates; date parsers returning null on unparseable input and passing it through.
Understand the failure class
Background: "Missing required field" and "field is required" errors: why libraries reject payloads that omit mandatory fields — this error's family across 20 libraries.
Related errors
- Amount is invalid, must be an integer: ${trans.amount}
- Filter name is required
- --table is required when the input file lacks a "table" fiel
- Unknown payee name normalization: ${String(normalization)}
- Subtransaction amount is invalid, must be an integer: ${sub.
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/72d2f85734894c22.
Report an issue: GitHub.