actualbudget/actual · error · Error
Invalid config file: unknown key "${key}"
Error message
Invalid config file: unknown key "${key}" What it means
When validating the CLI config file, every key present must be one of the recognized option names (serverUrl, password, sessionToken, syncId, dataDir, encryptionPassword, cacheTtl, lockTimeout, noLock). Any unknown key causes this error, so typos and renamed options are caught immediately instead of being silently ignored.
Source
Thrown at packages/cli/src/config.ts:78
noLock?: boolean;
};
const configFileKeys: readonly string[] = [
...stringKeys,
...numberKeys,
...booleanKeys,
];
function validateConfigFileContent(value: unknown): ConfigFileContent {
if (!isRecord(value)) {
throw new Error(
'Invalid config file: expected an object with keys: ' +
configFileKeys.join(', '),
);
}
for (const key of Object.keys(value)) {
if (!configFileKeys.includes(key)) {
throw new Error(`Invalid config file: unknown key "${key}"`);
}
const v = value[key];
if (v === undefined) continue;
if (
(stringKeys as readonly string[]).includes(key) &&
typeof v !== 'string'
) {
throw new Error(
`Invalid config file: key "${key}" must be a string, got ${typeof v}`,
);
}
if (
(numberKeys as readonly string[]).includes(key) &&
(typeof v !== 'number' || !Number.isInteger(v) || v < 0)
) {
throw new Error(
`Invalid config file: key "${key}" must be a non-negative integer`,
);View on GitHub (pinned to d4334cb6e6)
Solutions
- Remove or rename the offending key to one of: serverUrl, password, sessionToken, syncId, dataDir, encryptionPassword, cacheTtl, lockTimeout, noLock
- Check the error message — it names the exact unknown key; fix its casing/spelling
- If the option belongs to the sync-server, move it to the server's own config file
- Consult the CLI docs for your installed version to see current valid keys
Example fix
// before (actual.config.json)
{ "serverurl": "http://localhost:5006", "dataDir": "./data" }
// after
{ "serverUrl": "http://localhost:5006", "dataDir": "./data" } Defensive patterns
Strategy: validation
Validate before calling
const ALLOWED = ['serverUrl','password','sessionToken','syncId','dataDir','encryptionPassword','cacheTtl','lockTimeout','noLock'];
for (const k of Object.keys(cfg)) {
if (!ALLOWED.includes(k)) throw new Error(`Unknown CLI config key "${k}"`);
} Type guard
function onlyKnownKeys(v: Record<string, unknown>, allowed: readonly string[]): boolean {
return Object.keys(v).every(k => allowed.includes(k));
} Try / catch
try {
await run(['actual', 'accounts']);
} catch (e) {
if (String(e.message).includes('unknown key')) {
const key = /unknown key "(.+?)"/.exec(String(e.message))?.[1];
console.error(`Remove or rename "${key}" in your config file`);
} else throw e;
} Prevention
- Type keys exactly as documented: camelCase, e.g. serverUrl not serverurl or server-url
- Diff your config against the key list in the error message after CLI upgrades
- Keep server-only options out of the CLI config file
When it happens
Trigger: A config file containing `syncId` misspelled as `syncID` or `sync-id`; leftover keys from an older CLI version (e.g. removed options); keys meant for the sync-server config (like `serverFiles` or `port`) placed in the CLI config; camelCase mistakes such as `serverurl` or `data-dir`.
Common situations: Merging server config examples into the CLI config; upgrading/downgrading and carrying deprecated keys; documentation drift between versions.
Related errors
- Invalid config file: expected an object with keys: ${configF
- Invalid config file: key "${key}" must be a string, got ${ty
- Invalid config file: key "${key}" must be a non-negative int
- Invalid --name: must be a non-empty string.
- No update fields provided. Use --name or --offbudget.
AI-assisted analysis of actualbudget/actual@d4334cb6e6 (2026-08-29).
Data as JSON: /api/errors/ee3039f82ba91616.
Report an issue: GitHub.