{"record":{"id":"b27283a07ce594b8","repo":"actualbudget/actual","slug":"invalid-config-file-key-key-must-be-a-boolea","errorCode":null,"errorMessage":"Invalid config file: key \"${key}\" must be a boolean, got ${typeof v}","messagePattern":"Invalid config file: key \"(.+?)\" must be a boolean, got (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/cli/src/config.ts","lineNumber":102,"sourceCode":"      typeof v !== 'string'\n    ) {\n      throw new Error(\n        `Invalid config file: key \"${key}\" must be a string, got ${typeof v}`,\n      );\n    }\n    if (\n      (numberKeys as readonly string[]).includes(key) &&\n      (typeof v !== 'number' || !Number.isInteger(v) || v < 0)\n    ) {\n      throw new Error(\n        `Invalid config file: key \"${key}\" must be a non-negative integer`,\n      );\n    }\n    if (\n      (booleanKeys as readonly string[]).includes(key) &&\n      typeof v !== 'boolean'\n    ) {\n      throw new Error(\n        `Invalid config file: key \"${key}\" must be a boolean, got ${typeof v}`,\n      );\n    }\n  }\n  return value as ConfigFileContent;\n}\n\nasync function loadConfigFile(): Promise<ConfigFileContent> {\n  const explorer = cosmiconfig('actual', {\n    searchStrategy: 'global',\n    searchPlaces: [\n      'package.json',\n      '.actualrc',\n      '.actualrc.json',\n      '.actualrc.yaml',\n      '.actualrc.yml',\n      'actual.config.json',\n      'actual.config.yaml',","sourceCodeStart":84,"sourceCodeEnd":120,"githubUrl":"https://github.com/actualbudget/actual/blob/d4334cb6e6123f4d3bcea1ad6166608884c7e658/packages/cli/src/config.ts#L84-L120","documentation":"validateConfigFileContent enforces that keys in booleanKeys hold actual JSON booleans. The error message includes the received typeof so you can see what was actually supplied. It is thrown while type-checking the config file content before it is merged into the resolved configuration.","triggerScenarios":"A config file key listed in booleanKeys is set to a string like \"true\"/\"false\", or to a number 0/1, instead of a JSON true/false.","commonSituations":"Writing \"verbose\": \"true\" in JSON by hand; exporting env-style values into the config; generating the config with a tool that stringifies booleans.","solutions":["Edit the config file so the offending key is a real JSON boolean: true or false, unquoted.","Remove the key if you want the built-in default.","Search the config for quoted booleans (\"true\"/\"false\") to fix all occurrences at once."],"exampleFix":"// before (config.json)\n{ \"verbose\": \"true\" }\n// after\n{ \"verbose\": true }","handlingStrategy":"validation","validationCode":"function hasValidBooleans(cfg: Record<string, unknown>, booleanKeys: readonly string[]): boolean {\n  return booleanKeys.every(k => {\n    const v = cfg[k];\n    return v === undefined || typeof v === 'boolean';\n  });\n}","typeGuard":"function isBoolean(v: unknown): v is boolean {\n  return typeof v === 'boolean';\n}","tryCatchPattern":"try {\n  fileConfig = loadConfigFile(path);\n} catch (err) {\n  if (err instanceof Error && /must be a boolean/.test(err.message)) {\n    const key = /key \"([^\"]+)\"/.exec(err.message)?.[1];\n    console.error(`Fix ${key} in ${path}: it must be true or false (unquoted).`);\n    process.exit(1);\n  }\n  throw err;\n}","preventionTips":["In JSON, write booleans as true/false — never \"true\"/\"false\" or 0/1.","Generate config via a script using JSON.stringify to guarantee correct types.","Grep config files for /\"(true|false)\"/ to catch quoted booleans.","Validate the config against a schema before deployment."],"tags":["config","validation","types"],"backgroundTag":"schema-validation-failed","analyzedSha":"d4334cb6e6123f4d3bcea1ad6166608884c7e658","analyzedAt":"2026-08-29T01:02:11.213Z","schemaVersion":2},"datasetVersion":"2026-08-29T02:17:18.158Z"}