actualbudget/actual · error · Error

Server URL is required. Set --server-url, ACTUAL_SERVER_URL

Error message

Server URL is required. Set --server-url, ACTUAL_SERVER_URL env var, or serverUrl in config file.

What it means

resolveConfig merges CLI options, environment variables, and the config file, and requires a server URL to establish any connection. When none of --server-url, ACTUAL_SERVER_URL, or config file serverUrl is set, it throws this error before any network call is made.

Source

Thrown at packages/cli/src/config.ts:181

    process.env.ACTUAL_SESSION_TOKEN ??
    fileConfig.sessionToken;

  const syncId =
    cliOpts.syncId ?? process.env.ACTUAL_SYNC_ID ?? fileConfig.syncId;

  const dataDir =
    cliOpts.dataDir ??
    process.env.ACTUAL_DATA_DIR ??
    fileConfig.dataDir ??
    join(homedir(), '.actual-cli', 'data');

  const encryptionPassword =
    cliOpts.encryptionPassword ??
    process.env.ACTUAL_ENCRYPTION_PASSWORD ??
    fileConfig.encryptionPassword;

  if (!serverUrl) {
    throw new Error(
      'Server URL is required. Set --server-url, ACTUAL_SERVER_URL env var, or serverUrl in config file.',
    );
  }

  if (!password && !sessionToken) {
    throw new Error(
      'Authentication required. Set --password/--session-token, ACTUAL_PASSWORD/ACTUAL_SESSION_TOKEN env var, or password/sessionToken in config file.',
    );
  }

  const cacheTtl = validateNonNegativeInt(
    cliOpts.cacheTtl ??
      parseNonNegativeIntEnv(
        process.env.ACTUAL_CACHE_TTL,
        'ACTUAL_CACHE_TTL',
      ) ??
      fileConfig.cacheTtl ??
      60,

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Pass --server-url=https://your-actual-server (or the appropriate flag for the command).
  2. Export ACTUAL_SERVER_URL in your shell/CI environment.
  3. Add "serverUrl": "https://your-actual-server" to the config file.
  4. Verify the config file you edited is the one being loaded (check the config path resolution).

Example fix

// before (CI env)
ACTUAL_PASSWORD=secret
// after
ACTUAL_PASSWORD=secret
ACTUAL_SERVER_URL=https://actual.example.com
Defensive patterns

Strategy: validation

Validate before calling

const serverUrl = cliOpts.serverUrl ?? process.env.ACTUAL_SERVER_URL ?? fileConfig.serverUrl;
if (!serverUrl) {
  throw new Error('Server URL is required. Set --server-url, ACTUAL_SERVER_URL, or serverUrl in config file.');
}

Type guard

function hasServerUrl(o: { serverUrl?: string }): o is { serverUrl: string } & typeof o {
  return typeof o.serverUrl === 'string' && o.serverUrl.length > 0;
}

Try / catch

try {
  const config = await config(opts);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Server URL is required')) {
    console.error('Set ACTUAL_SERVER_URL or pass --server-url.');
    process.exit(1);
  }
  throw err;
}

Prevention

When it happens

Trigger: Running any command that calls config()/resolveConfig with no --server-url flag, no ACTUAL_SERVER_URL env var, and no serverUrl key in the config file.

Common situations: Fresh CI setup where only ACTUAL_PASSWORD was exported; forgetting the config file lives in a different directory than expected so it is never read; switching from the desktop app to CLI where the URL was previously implicit.

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/fa7e582e4bfb4b2b. Report an issue: GitHub.