actualbudget/actual · error · Error

ACTUAL_DATA_DIR is not set

Error message

ACTUAL_DATA_DIR is not set

What it means

`getDataDir` in the Electron window-state module reads `ACTUAL_DATA_DIR` to know where to persist window state (position/size) JSON. If the env var is missing it throws rather than guessing a directory, because the desktop app sets this variable during startup.

Source

Thrown at packages/desktop-electron/window-state.ts:15

import fs from 'fs';
import path from 'path';

import electron from 'electron';
import type { BrowserWindow } from 'electron';

type WindowState = Electron.Rectangle & {
  isMaximized?: boolean;
  isFullScreen?: boolean;
  displayBounds?: Electron.Rectangle;
};

const getDataDir = () => {
  if (!process.env.ACTUAL_DATA_DIR) {
    throw new Error('ACTUAL_DATA_DIR is not set');
  }

  return process.env.ACTUAL_DATA_DIR;
};

async function loadState() {
  let state: WindowState | undefined = undefined;
  try {
    state = JSON.parse(
      fs.readFileSync(path.join(getDataDir(), 'window.json'), 'utf8'),
    );
  } catch {
    console.log('Could not load window state');
  }

  return validateState(state);
}

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Set `ACTUAL_DATA_DIR` to the app's user-data directory (e.g. `app.getPath('userData')`) before loading the window-state module
  2. Launch the app via the standard scripts/builds that set the env var
  3. In tests, set `process.env.ACTUAL_DATA_DIR` to a temp directory in your setup fixture

Example fix

// before
import { loadState } from './window-state';
// after
process.env.ACTUAL_DATA_DIR ??= app.getPath('userData');
import { loadState } from './window-state';
Defensive patterns

Strategy: validation

Validate before calling

if (!process.env.ACTUAL_DATA_DIR) {
  process.env.ACTUAL_DATA_DIR = require('electron').app.getPath('userData');
}

Try / catch

try {
  const state = loadState();
} catch (e) {
  if (String(e).includes('ACTUAL_DATA_DIR is not set')) {
    // fall back to defaults / re-set env and retry
  } else throw e;
}

Prevention

When it happens

Trigger: Calling `loadState()` or `saveState()` from `window-state.ts` when the Electron main process environment lacks `ACTUAL_DATA_DIR` — e.g. launching the app outside its normal launcher scripts.

Common situations: Running the electron main file directly with node/electron CLI; custom launchers or test harnesses that don't replicate the production env; refactors that call window-state functions before env setup.

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


AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29). Data as JSON: /api/errors/9231d7180df25c18. Report an issue: GitHub.