actualbudget/actual · critical · Error
ACTUAL_DATA_DIR env variable is required
Error message
ACTUAL_DATA_DIR env variable is required
What it means
The Electron build of the server `fs` module resolves every file operation against `ACTUAL_DATA_DIR`. If the env var is unset, `getDataDir` throws because there is no safe default location for user data (budget files, sqlite DBs) in the desktop app.
Source
Thrown at packages/loot-core/src/platform/server/fs/index.electron.ts:28
export { getDocumentDir, getBudgetDir, _setDocumentDir } from './shared';
let rootPath = path.join(__dirname, '..', '..', '..', '..');
switch (path.basename(__filename)) {
case 'bundle.desktop.js': // electron app
rootPath = path.join(__dirname, '..', '..');
break;
default:
break;
}
export const init: typeof T.init = async () => {
// Nothing to do
};
export const getDataDir: typeof T.getDataDir = () => {
if (!process.env.ACTUAL_DATA_DIR) {
throw new Error('ACTUAL_DATA_DIR env variable is required');
}
return process.env.ACTUAL_DATA_DIR;
};
export const bundledDatabasePath: typeof T.bundledDatabasePath = path.join(
rootPath,
'default-db.sqlite',
);
export const migrationsPath: typeof T.migrationsPath = path.join(
rootPath,
'migrations',
);
export const demoBudgetPath: typeof T.demoBudgetPath = path.join(
rootPath,
'demo-budget',
);View on GitHub (pinned to d4334cb6e6)
Solutions
- Set `ACTUAL_DATA_DIR` in the Electron main process (typically `app.getPath('userData')`) before lazy-loading the backend bundle
- Launch via the app's standard scripts that configure the environment
- In tests, assign `process.env.ACTUAL_DATA_DIR = os.tmpdir()` in setup
Example fix
// before
const { initApp } = await import(process.env.lootCoreScript);
// after
process.env.ACTUAL_DATA_DIR ??= app.getPath('userData');
const { initApp } = await import(process.env.lootCoreScript); Defensive patterns
Strategy: validation
Validate before calling
if (!process.env.ACTUAL_DATA_DIR) {
throw new Error('Initialize ACTUAL_DATA_DIR (e.g. app.getPath(userData)) before using electron fs.');
} Try / catch
try {
const dir = getDataDir();
} catch (e) {
if (String(e).includes('ACTUAL_DATA_DIR')) {
process.env.ACTUAL_DATA_DIR = app.getPath('userData');
} else throw e;
} Prevention
- Configure the env var in the main process before importing the server bundle
- Never launch the packaged backend with a bare `electron .` outside the standard entry
- Add a startup assertion that the data dir exists and is writable
When it happens
Trigger: Any fs operation that routes through `getDataDir` (path resolution for budgets, backups, migrations) in the Electron backend when `process.env.ACTUAL_DATA_DIR` is undefined.
Common situations: Launching the packaged Electron backend outside its normal entry point; the main process failing to set the env var before importing the server bundle; test harnesses exercising `fs/index.electron.ts` directly.
Understand the failure class
Background: "environment variable is not set" and "Missing keys in environment" errors: what missing required env var messages mean and how to fix them — this error's family across 28 libraries.
Related errors
- The environment variable `lootCoreScript` is not defined. Pl
- ACTUAL_DATA_DIR is not set
- applyAppUpdate not implemented in electron app
- Failed to init the server bundle after all retries: ${String
- File does not exist: ${filepath}
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/c30be171f69519f9.
Report an issue: GitHub.