actualbudget/actual · error
Either `filepath` or `buffer` must be given
Error message
Either `filepath` or `buffer` must be given
What it means
`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.
Source
Thrown at packages/loot-core/src/server/budgetfiles/app.ts:499
* to derive the budget name for some import types.
*/
filename?: string;
}): Promise<{ error?: string; meta?: unknown; id?: string }> {
try {
let contents: Buffer;
let name: string;
if (filepath != null) {
if (!(await fs.exists(filepath))) {
throw new Error(`File not found at the provided path: ${filepath}`);
}
contents = Buffer.from(await fs.readFile(filepath, 'binary'));
name = filepath;
} else if (buffer != null) {
contents = Buffer.from(buffer);
name = filename || 'budget-import';
} else {
throw new Error('Either `filepath` or `buffer` must be given');
}
const results = await handleBudgetImport(type, name, contents);
if (results && results.error) {
return results;
}
// A successful import leaves the imported budget loaded
return { id: prefs.getPrefs()?.id };
} catch (err) {
err.message = 'Error importing budget: ' + err.message;
captureException(err);
return { error: 'internal-error' };
}
}
async function exportBudget() {
try {
const exported = await cloudStorage.exportBuffer();View on GitHub (pinned to d4334cb6e6)
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.
Example fix
// before
await importBudget({ type: 'ynab4' }); // neither source given
// after
const contents = await fs.readFile('budget.yfull');
await importBudget({ type: 'ynab4', buffer: contents }); Defensive patterns
Strategy: validation
Validate before calling
function assertImportSource(params) {
const hasPath = typeof params.filepath === 'string' && params.filepath.length > 0;
const hasBuffer = params.buffer != null && params.buffer.length > 0;
if (!hasPath && !hasBuffer) {
throw new Error('importBudget requires a non-empty `filepath` or `buffer`');
}
} Type guard
function hasImportSource(params) {
return (
(typeof params.filepath === 'string' && params.filepath.length > 0) ||
(params.buffer instanceof Uint8Array && params.buffer.length > 0)
);
} Try / catch
try {
await importBudget({ type, filepath, buffer });
} catch (e) {
if (e.message.includes('`filepath` or `buffer` must be given')) {
console.error('No import source provided — attach the uploaded file first');
} else {
throw e;
}
} Prevention
- 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
When it happens
Trigger: 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).
Common situations: 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.
Understand the failure class
Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.
Related errors
- No fields to update. Use --name to specify a new name.
- No valid payee IDs provided in --ids. Provide comma-separate
- --table is required (or use --file or --last)
- Invalid dashboard.widgets data type: it must be an array of
- Invalid widget.${idx}.x data-type for value ${widget.x}.
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/854d75c03f869f8e.
Report an issue: GitHub.