{"record":{"id":"854d75c03f869f8e","repo":"actualbudget/actual","slug":"either-filepath-or-buffer-must-be-given","errorCode":null,"errorMessage":"Either `filepath` or `buffer` must be given","messagePattern":"Either `filepath` or `buffer` must be given","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/loot-core/src/server/budgetfiles/app.ts","lineNumber":499,"sourceCode":"   * to derive the budget name for some import types.\n   */\n  filename?: string;\n}): Promise<{ error?: string; meta?: unknown; id?: string }> {\n  try {\n    let contents: Buffer;\n    let name: string;\n    if (filepath != null) {\n      if (!(await fs.exists(filepath))) {\n        throw new Error(`File not found at the provided path: ${filepath}`);\n      }\n\n      contents = Buffer.from(await fs.readFile(filepath, 'binary'));\n      name = filepath;\n    } else if (buffer != null) {\n      contents = Buffer.from(buffer);\n      name = filename || 'budget-import';\n    } else {\n      throw new Error('Either `filepath` or `buffer` must be given');\n    }\n\n    const results = await handleBudgetImport(type, name, contents);\n    if (results && results.error) {\n      return results;\n    }\n    // A successful import leaves the imported budget loaded\n    return { id: prefs.getPrefs()?.id };\n  } catch (err) {\n    err.message = 'Error importing budget: ' + err.message;\n    captureException(err);\n    return { error: 'internal-error' };\n  }\n}\n\nasync function exportBudget() {\n  try {\n    const exported = await cloudStorage.exportBuffer();","sourceCodeStart":481,"sourceCodeEnd":517,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/loot-core/src/server/budgetfiles/app.ts#L481-L517","documentation":"`importBudget` requires exactly one input source: a `filepath` on disk or an in-memory `buffer`. If neither is provided (both undefined/null), the function throws this guard error instead of proceeding. It is a straightforward precondition check so callers fail fast with an unambiguous message.","triggerScenarios":"Calling `importBudget({ type })` with no source at all; passing both `filepath: undefined` and `buffer: undefined` due to a failed destructuring or an object built conditionally where the key was omitted; passing empty strings or `null` (which fail the `!= null` / truthiness checks used to pick the branch).","commonSituations":"API consumers reading the source/params from a request body where the file field was not uploaded; a wrapper function forwarding `undefined` because an earlier await failed silently; TypeScript callers relying on optional props and never setting either; switching code from `filepath` to `buffer` (or vice versa) but deleting one key without setting the other.","solutions":["Pass either `filepath` (an existing server-side path) or `buffer` (a Uint8Array/Buffer of the file contents) to `importBudget`.","If the data comes from an upload or the client, prefer the `buffer` form: `Buffer.from(await file.arrayBuffer())`.","Validate before calling: reject requests where both fields are missing with your own clear message.","Check for empty-string values — `''` and `null` will both land in this error branch; require a non-empty path string."],"exampleFix":"// before\nawait importBudget({ type: 'ynab4' }); // neither source given\n\n// after\nconst contents = await fs.readFile('budget.yfull');\nawait importBudget({ type: 'ynab4', buffer: contents });","handlingStrategy":"validation","validationCode":"function assertImportSource(params) {\n  const hasPath = typeof params.filepath === 'string' && params.filepath.length > 0;\n  const hasBuffer = params.buffer != null && params.buffer.length > 0;\n  if (!hasPath && !hasBuffer) {\n    throw new Error('importBudget requires a non-empty `filepath` or `buffer`');\n  }\n}","typeGuard":"function hasImportSource(params) {\n  return (\n    (typeof params.filepath === 'string' && params.filepath.length > 0) ||\n    (params.buffer instanceof Uint8Array && params.buffer.length > 0)\n  );\n}","tryCatchPattern":"try {\n  await importBudget({ type, filepath, buffer });\n} catch (e) {\n  if (e.message.includes('`filepath` or `buffer` must be given')) {\n    console.error('No import source provided — attach the uploaded file first');\n  } else {\n    throw e;\n  }\n}","preventionTips":["Make `filepath`/`buffer` required in your wrapper's signature so TypeScript catches omissions","Guard request handlers: reject uploads where the file field is absent before calling importBudget","Remember empty strings and null both hit this branch — require non-empty values","Prefer the buffer path for client-side data; it removes filesystem path concerns entirely"],"tags":["import","validation","missing-argument"],"backgroundTag":"missing-required-argument","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}