{"record":{"id":"4379feb1b7f0f109","repo":"actualbudget/actual","slug":"throw-error-errormsg","errorCode":null,"errorMessage":"throw Error(errorMsg)","messagePattern":"throw Error\\(errorMsg\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/importers/ynab5.ts","lineNumber":890,"sourceCode":"    payee: string;\n    account: string;\n    amount: number;\n    amountOp: 'is';\n    date: RecurConfig | string;\n  }) {\n    const baseName = params.name;\n    let count = 1;\n\n    while (true) {\n      try {\n        return await send('api/schedule-create', {\n          ...params,\n          name: params.name,\n        });\n      } catch (e) {\n        if (count >= MAX_RETRY) {\n          const errorMsg = normalizeError(e);\n          throw Error(errorMsg);\n        }\n        params.name = `${baseName} (${count})`;\n        count += 1;\n      }\n    }\n  }\n\n  async function getRuleForSchedule(\n    scheduleId: string,\n  ): Promise<RuleEntity | null> {\n    const { data: ruleId } = (await send('api/query', {\n      query: q('schedules')\n        .filter({ id: scheduleId })\n        .calculate('rule')\n        .serialize(),\n    })) as { data: string | null };\n    if (!ruleId) {\n      return null;","sourceCodeStart":872,"sourceCodeEnd":908,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/importers/ynab5.ts#L872-L908","documentation":"During YNAB5 budget import, schedule creation retries with a suffixed name ('Name (1)', 'Name (2)') when a schedule with the same name exists. If the api/schedule-create call keeps failing after MAX_RETRY attempts, the last error is normalized and rethrown as a plain Error. This means the import could not create a schedule even after de-duplication attempts, so the failure is usually not about the name at all.","triggerScenarios":"createScheduleWithUniqueName calls send('api/schedule-create', ...) and the call throws MAX_RETRY consecutive times: e.g. invalid recurring date config (bad RecurConfig from the YNAB file), invalid payee/account ids, or a persistent server-side validation error that does not disappear when the name changes.","commonSituations":"Importing a YNAB budget whose scheduled transaction has a malformed or unsupported recurrence pattern; corrupted ids referenced by the schedule; a bug/regression in schedule-create validation rejecting the payload regardless of name.","solutions":["Inspect the normalized error message to find the real cause — it is the underlying schedule-create failure, not a name collision","Validate the YNAB file's scheduled transaction date/recurrence data before import","Check that the referenced payee and account were successfully imported and exist","Retry the import after fixing the budget file; if it persists, file an issue with the schedule payload"],"exampleFix":"// before (retry loop rethrows opaque error)\nif (count >= MAX_RETRY) {\n  const errorMsg = normalizeError(e);\n  throw Error(errorMsg);\n}\n// after (preserve cause and context)\nif (count >= MAX_RETRY) {\n  throw new Error(\n    `Failed to create schedule \"${baseName}\" after ${count} attempts: ${normalizeError(e)}`,\n    { cause: e },\n  );\n}","handlingStrategy":"try-catch","validationCode":"// Pre-check for an existing schedule with the same name before import\nconst existing = await send('api/query', {\n  query: q('schedules').filter({ name: scheduleName }).select('id'),\n});\nif (existing.data.length > 0) console.warn(`Schedule \"${scheduleName}\" exists; importer will rename`);","typeGuard":"function isRetryableScheduleError(e: unknown): boolean {\n  const msg = e instanceof Error ? e.message : String(e);\n  return /already exists|duplicate/i.test(msg);\n}","tryCatchPattern":"try {\n  await doYnab5Import(buffer);\n} catch (e) {\n  const msg = e instanceof Error ? e.message : String(e);\n  if (/schedule/i.test(msg)) {\n    console.error('Schedule import failed:', msg); // inspect underlying cause\n  } else {\n    throw e;\n  }\n}","preventionTips":["Validate the YNAB export's scheduled transaction recurrence data before importing","Ensure payees/accounts referenced by schedules import successfully (they are created earlier in the pipeline)","Uniquify schedule names in the source file to avoid exercising the retry path","Check the underlying error message — name collision is auto-handled, so failure means a deeper validation problem"],"tags":["import","ynab5","schedules","validation"],"backgroundTag":"schedule-import-failed","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}