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

  1. Ensure one start date per account, in the same order as the accountId array.
  2. Rebuild the payload by mapping accounts to dates in a single pass so the arrays stay aligned.
  3. If all accounts share a start date, either repeat it N times or use the single-string form only when calling with one account.
  4. 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

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


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/53872aa030fdf3eb. Report an issue: GitHub.