{"record":{"id":"00c01394be28b7a8","repo":"actualbudget/actual","slug":"transactions-import-payeenamenormalization-must-b","errorCode":null,"errorMessage":"transactions-import: payeeNameNormalization must be one of ${bankSync.PAYEE_NAME_NORMALIZATIONS.join(', ')}, got '${String(payeeNameNormalization)}'","messagePattern":"transactions-import: payeeNameNormalization must be one of (.+?), got '(.+?)'","errorType":"exception","errorClass":"APIError","httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/accounts/app.ts","lineNumber":1651,"sourceCode":"\nasync function importTransactions({\n  accountId,\n  transactions,\n  isPreview,\n  opts,\n}: {\n  accountId: AccountEntity['id'];\n  transactions: ImportTransactionEntity[];\n  isPreview: boolean;\n  opts?: ImportTransactionsOpts;\n}): Promise<ImportTransactionsResult> {\n  if (typeof accountId !== 'string') {\n    throw APIError('transactions-import: accountId must be an id');\n  }\n\n  const payeeNameNormalization = opts?.payeeNameNormalization ?? 'title-case';\n  if (!bankSync.PAYEE_NAME_NORMALIZATIONS.includes(payeeNameNormalization)) {\n    throw APIError(\n      `transactions-import: payeeNameNormalization must be one of ${bankSync.PAYEE_NAME_NORMALIZATIONS.join(\n        ', ',\n      )}, got '${String(payeeNameNormalization)}'`,\n    );\n  }\n\n  try {\n    const reconciled = await bankSync.reconcileTransactions(\n      accountId,\n      transactions,\n      {\n        isPreview,\n        defaultCleared: opts?.defaultCleared,\n        reimportDeleted: opts?.reimportDeleted,\n        payeeNameNormalization,\n      },\n    );\n    return {","sourceCodeStart":1633,"sourceCodeEnd":1669,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/accounts/app.ts#L1633-L1669","documentation":"The transactions-import API accepts an optional opts.payeeNameNormalization that controls how payee names are normalized during reconciliation. The value must be one of PAYEE_NAME_NORMALIZATIONS = ['original', 'title-case'] (sync.ts:416); anything else, including typos or differently-cased values, throws this APIError before any import runs. It defaults to 'title-case' when omitted.","triggerScenarios":"Calling importTransactions with opts.payeeNameNormalization set to anything other than 'original' or 'title-case', e.g. 'Title-Case', 'lowercase', 'none', or an outdated value from an older API version.","commonSituations":"Copy-pasting option names from old docs or blog posts; case-mismatched enum values from loosely typed JS callers; a config UI passing user-entered text instead of a constrained select value.","solutions":["Set opts.payeeNameNormalization to exactly 'title-case' or 'original' (lowercase).","Omit the option entirely to accept the 'title-case' default.","Validate the value against PAYEE_NAME_NORMALIZATIONS before calling (the array is exported from loot-core's bankSync module).","If migrating from an older version, update stale option values to the current enum."],"exampleFix":"// before\nawait importTransactions({ accountId, transactions, isPreview: false, opts: { payeeNameNormalization: 'Title Case' } });\n// after\nawait importTransactions({ accountId, transactions, isPreview: false, opts: { payeeNameNormalization: 'title-case' } });","handlingStrategy":"validation","validationCode":"const ALLOWED = ['original', 'title-case'];\nif (opts?.payeeNameNormalization && !ALLOWED.includes(opts.payeeNameNormalization)) {\n  throw new Error(`payeeNameNormalization must be one of ${ALLOWED.join(', ')}`);\n}","typeGuard":"const PAYEE_NAME_NORMALIZATIONS = ['original', 'title-case'] as const;\ntype PayeeNameNormalization = (typeof PAYEE_NAME_NORMALIZATIONS)[number];\nfunction isPayeeNameNormalization(v: unknown): v is PayeeNameNormalization {\n  return typeof v === 'string' && (PAYEE_NAME_NORMALIZATIONS as readonly string[]).includes(v);\n}","tryCatchPattern":"try {\n  await api.transactionsImport(accountId, txns, opts);\n} catch (e) {\n  if (e instanceof APIError && e.message.includes('payeeNameNormalization')) {\n    // fall back to the default\n    await api.transactionsImport(accountId, txns, { ...opts, payeeNameNormalization: 'title-case' });\n  } else throw e;\n}","preventionTips":["Use the exported PAYEE_NAME_NORMALIZATIONS const / PayeeNameNormalization type instead of raw strings.","Rely on the 'title-case' default unless normalization is explicitly needed.","Build config UIs as a constrained select of the two allowed values.","Grep for the option name in release notes when upgrading — the enum can grow."],"tags":["validation","api","enum","payee"],"backgroundTag":"invalid-enum-value","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}