actualbudget/actual · error · Error

Invalid ${name}: expected a non-negative integer, got ${valu

Error message

Invalid ${name}: expected a non-negative integer, got ${value}

What it means

validateNonNegativeInt is a final guard applied to resolved numeric options (cacheTtl, lockTimeout) after CLI/env/config merging. It throws when a value reached it that is not an integer or is negative. It backs the earlier parseNonNegativeIntFlag parsing so non-numeric option strings fail too.

Source

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

    ],
  });
  const result = await explorer.search();
  if (result && !result.isEmpty) {
    return validateConfigFileContent(result.config);
  }
  return {};
}

function parseNonNegativeIntEnv(
  raw: string | undefined,
  source: string,
): number | undefined {
  return raw === undefined ? undefined : parseNonNegativeIntFlag(raw, source);
}

function validateNonNegativeInt(value: number, name: string): number {
  if (!Number.isInteger(value) || value < 0) {
    throw new Error(
      `Invalid ${name}: expected a non-negative integer, got ${value}`,
    );
  }
  return value;
}

export async function resolveConfig(
  cliOpts: CliGlobalOpts,
): Promise<CliConfig> {
  const fileConfig = await loadConfigFile();

  const serverUrl =
    cliOpts.serverUrl ??
    process.env.ACTUAL_SERVER_URL ??
    fileConfig.serverUrl ??
    '';

  const password =

View on GitHub (pinned to d4334cb6e6)

Solutions

  1. Change the option value to a non-negative integer, e.g. --cache-ttl=300.
  2. Remove the flag/env/config entry to use the default value.
  3. If you need to disable caching, check the docs for the supported mechanism rather than using -1.

Example fix

// before
$ actual-cli --cache-ttl=-1
// after
$ actual-cli --cache-ttl=300
Defensive patterns

Strategy: validation

Validate before calling

const raw = process.env.ACTUAL_CACHE_TTL;
if (raw !== undefined && (!/^[0-9]+$/.test(raw) || parseInt(raw, 10) < 0)) {
  throw new Error(`ACTUAL_CACHE_TTL must be a non-negative integer, got ${raw}`);
}

Type guard

function isNonNegativeInt(v: unknown): v is number {
  return typeof v === 'number' && Number.isInteger(v) && v >= 0;
}

Try / catch

try {
  await runCommand(argv);
} catch (err) {
  if (err instanceof Error && err.message.startsWith('Invalid ')) {
    console.error(`Bad numeric option: ${err.message}`);
    process.exit(2);
  }
  throw err;
}

Prevention

When it happens

Trigger: Passing --cache-ttl=-1 or --lock-timeout=abc, setting ACTUAL_CACHE_TTL / ACTUAL_LOCK_TIMEOUT to a negative or non-numeric string, or a config file supplying -1 for these keys.

Common situations: Using -1 to mean 'infinite' (unsupported); typos like 3o instead of 30; leaving a stray minus sign in an env var.

Understand the failure class

Background: "Unknown argument", "Invalid value", and "must be one of": invalid CLI argument errors explained — this error's family across 35 libraries.

Related errors


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