actualbudget/actual · error
accountId and startDate arrays must be the same length
Error message
accountId and startDate arrays must be the same length
What it means
In batch mode, the SimpleFIN handler requires the accountId and startDate arrays to have the same length so each account can be paired with its own start date. When the lengths differ it throws 'accountId and startDate arrays must be the same length'. This prevents silently misaligning accounts to dates in the subsequent zip/reduce.
Source
Thrown at packages/sync-server/src/app-simplefin/app-simplefin.js:110
handleError(async (req, res) => {
const { accountId, startDate } = req.body || {};
const accessKey = secretsService.get(SecretName.simplefin_accessKey);
if (isInvalidAccessKey(accessKey)) {
invalidToken(res);
return;
}
if (Array.isArray(accountId) !== Array.isArray(startDate)) {
console.log({ accountId, startDate });
throw new Error(
'accountId and startDate must either both be arrays or both be strings',
);
}
if (Array.isArray(accountId) && accountId.length !== startDate.length) {
console.log({ accountId, startDate });
throw new Error('accountId and startDate arrays must be the same length');
}
const earliestStartDate = Array.isArray(startDate)
? startDate.reduce((a, b) => (a < b ? a : b))
: startDate;
let results;
try {
results = await getTransactions(
accessKey,
Array.isArray(accountId) ? accountId : [accountId],
new Date(earliestStartDate),
);
} catch (e) {
if (isForbidden(e.message)) {
invalidToken(res);
} else {
serverDown(e, res);
}View on GitHub (pinned to d4334cb6e6)
Solutions
- Ensure one start date per account, in the same order as the accountId array.
- Rebuild the payload by mapping accounts to dates in a single pass so the arrays stay aligned.
- If all accounts share a start date, either repeat it N times or use the single-string form only when calling with one account.
- Assert equal lengths in the caller before sending the request.
Example fix
// before
const payload = { accountId: accounts, startDate: dates.slice(0, 2) };
// after
if (accounts.length !== dates.length) throw new Error('accounts/dates length mismatch');
const payload = { accountId: accounts, startDate: accounts.map(a => startDateByAccount[a]) }; Defensive patterns
Strategy: validation
Validate before calling
if (Array.isArray(accountId) && accountId.length !== startDate.length) {
throw new Error('accountId and startDate arrays must be the same length');
} Prevention
- Construct batch payloads by mapping over accounts so dates can't drift out of alignment.
- Assert equal lengths in integration tests for the batch endpoint.
- Prefer a single source of truth (array of {accountId, startDate} pairs) flattened at call time.
When it happens
Trigger: Calling the SimpleFIN transactions endpoint with N account ids but M start dates where N !== M, e.g. adding a third account to the request but forgetting to add its start date.
Common situations: Dynamically building the batch payload and appending an account without the matching date; mapping over accounts but filtering some start dates; client caching an old date array after the account list changed.
Related errors
- accountId and startDate must either both be arrays or both b
- Invalid access key
- Invalid --name: must be a non-empty string.
- No update fields provided. Use --name or --offbudget.
- Invalid cutoff date: expected a valid date (e.g. YYYY-MM-DD)
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/53872aa030fdf3eb.
Report an issue: GitHub.