{"record":{"id":"101659129fa4f9ca","repo":"actualbudget/actual","slug":"unknown-payee-name-normalization-string-normali","errorCode":null,"errorMessage":"Unknown payee name normalization: ${String(normalization)}","messagePattern":"Unknown payee name normalization: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/accounts/sync.ts","lineNumber":430,"sourceCode":"\n  return trans.payee;\n}\n\nexport const PAYEE_NAME_NORMALIZATIONS = ['original', 'title-case'] as const;\nexport type PayeeNameNormalization = (typeof PAYEE_NAME_NORMALIZATIONS)[number];\n\nfunction normalizePayeeName(\n  payeeName: string,\n  normalization: PayeeNameNormalization,\n): string {\n  switch (normalization) {\n    case 'original':\n      return payeeName;\n    case 'title-case':\n      return title(payeeName);\n    default:\n      normalization satisfies never;\n      throw new Error(\n        `Unknown payee name normalization: ${String(normalization)}`,\n      );\n  }\n}\n\nasync function normalizeTransactions(\n  transactions,\n  acctId,\n  {\n    payeeNameNormalization = 'title-case',\n  }: {\n    payeeNameNormalization?: PayeeNameNormalization;\n  } = {},\n) {\n  const payeesToCreate = new Map();\n\n  const normalized = [];\n  for (let trans of transactions) {","sourceCodeStart":412,"sourceCodeEnd":448,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/accounts/sync.ts#L412-L448","documentation":"normalizePayeeName applies one of a fixed set of normalizations ('original' or 'title-case') to payee names during transaction sync. A `satisfies never` guard makes the switch exhaustive at compile time; at runtime an unrecognized value falls through to this throw. It protects the sync pipeline from invalid normalization options coming from callers.","triggerScenarios":"Calling the transactions-sync path (normalizeTransactions, e.g. via importTransactions) with a payee-name normalization value other than 'original' or 'title-case' — e.g. 'titlecase', 'capitalize', or an option from a mismatched client version.","commonSituations":"API integrations passing free-form strings for the option; version drift where a caller uses an option added in a newer/older version than the running core; scripts copying option names with wrong spelling/casing.","solutions":["Change the normalization value to exactly 'original' or 'title-case'.","Check the option's source (API payload, config) for typos and casing ('title-case', not 'titlecase').","Pin your API client version to match the running Actual version.","Log the incoming normalization value at the boundary to catch bad payloads early."],"exampleFix":"// before\nnormalizeTransactions({ normalization: 'titlecase' });\n// after\nnormalizeTransactions({ normalization: 'title-case' }); // 'original' | 'title-case'","handlingStrategy":"type-guard","validationCode":"const NORMALIZATIONS = ['original', 'title-case'] as const;\ntype Normalization = (typeof NORMALIZATIONS)[number];\nif (!NORMALIZATIONS.includes(opts.normalization as Normalization)) {\n  throw new Error(`normalization must be one of ${NORMALIZATIONS.join(', ')}`);\n}","typeGuard":"function isNormalization(v: unknown): v is 'original' | 'title-case' {\n  return v === 'original' || v === 'title-case';\n}","tryCatchPattern":"try {\n  await importTransactions(accountId, txs, opts);\n} catch (e) {\n  if (e instanceof Error && e.message.startsWith('Unknown payee name normalization')) {\n    console.error('Fix the normalization option; use \"original\" or \"title-case\"');\n    return;\n  }\n  throw e;\n}","preventionTips":["Type the option as the literal union ('original' | 'title-case') so typos fail at compile time.","Copy option names from the API type definitions, not from memory.","Boundary-check any user/CLI input that maps to this option.","Keep API client and server versions in sync."],"tags":["validation","typescript","api"],"backgroundTag":"invalid-enum-value","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}