{"record":{"id":"c3cea87bd0813762","repo":"dmtrKovalenko/fff","slug":"unknown-option-key","errorCode":null,"errorMessage":"unknown option \"${key}\"","messagePattern":"unknown option \"(.+?)\"","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/pi-fff/src/config.ts","lineNumber":58,"sourceCode":"    throw new Error(\n      `Could not read pi-fff config at ${configPath}: ${errorMessage(error)}`,\n    );\n  }\n\n  let parsed: unknown;\n  try {\n    parsed = JSON.parse(contents);\n  } catch (error: unknown) {\n    throw invalidConfig(configPath, `not valid JSON (${errorMessage(error)})`);\n  }\n\n  if (!isRecord(parsed)) {\n    throw invalidConfig(configPath, \"expected a JSON object\");\n  }\n\n  for (const key of Object.keys(parsed)) {\n    if (!CONFIG_KEYS.has(key as keyof FffConfig)) {\n      throw invalidConfig(configPath, `unknown option \"${key}\"`);\n    }\n  }\n\n  if (parsed.mode !== undefined && !VALID_MODES.includes(parsed.mode as FffMode)) {\n    throw invalidConfig(configPath, `\"mode\" must be one of ${VALID_MODES.join(\", \")}`);\n  }\n\n  validateString(configPath, parsed, \"$schema\");\n  validateString(configPath, parsed, \"frecencyDbPath\");\n  validateString(configPath, parsed, \"historyDbPath\");\n  validateBoolean(configPath, parsed, \"enableFsRootScanning\");\n  validateBoolean(configPath, parsed, \"enableHomeDirScanning\");\n  validateBoolean(configPath, parsed, \"warnOnHomeDirScan\");\n  validateBoolean(configPath, parsed, \"followSymlinks\");\n\n  return parsed as FffConfig;\n}\n","sourceCodeStart":40,"sourceCodeEnd":76,"githubUrl":"https://github.com/dmtrKovalenko/fff/blob/7f8537e70f0ea1210f9acbbfc4640141105cdc78/packages/pi-fff/src/config.ts#L40-L76","documentation":"loadConfig validates every top-level key of pi-fff.json against the fixed set of known options ($schema, mode, frecencyDbPath, historyDbPath, enableFsRootScanning, enableHomeDirScanning, warnOnHomeDirScan, followSymlinks). If the JSON object contains any key outside that allowlist, loadConfig throws `Invalid pi-fff config at <path>: unknown option \"<key>\"` to fail fast on typos or stale options instead of silently ignoring them.","triggerScenarios":"Any top-level key in the pi-fff.json config file that is not in CONFIG_KEYS — e.g. a typo like \"frecencyPath\" instead of \"frecencyDbPath\", a stale/renamed option from an older release, or a mispasted key from another tool's config. CaSe matters: \"Mode\" or \"mode:\" variants also fail since the check is exact-string via Set.has.","commonSituations":"Hand-editing the config file and typo-ing a key; upgrading/downgrading the package and copying an example config that references options renamed or removed in this version; following outdated docs or a blog post that used an old option name; copy-pasting a config from a similarly named plugin.","solutions":["Open the config file named in the error message and remove or rename the reported key to a valid one: mode, frecencyDbPath, historyDbPath, enableFsRootScanning, enableHomeDirScanning, warnOnHomeDirScan, followSymlinks, $schema","Check the key's spelling and casing against FffConfig in packages/pi-fff/src/config.ts (exact camelCase match is required)","If the option was removed or renamed in a newer/older version of the package, align your config with the docs for the installed version","If the option is genuinely useful, file an issue/PR to add it to CONFIG_KEYS rather than bypassing validation"],"exampleFix":"// before (pi-fff.json)\n{\n  \"$schema\": \"https://example.com/pi-fff.schema.json\",\n  \"frecencyPath\": \"~/.local/share/pi/frecency\",\n  \"Mode\": \"tools-only\"\n}\n\n// after\n{\n  \"$schema\": \"https://example.com/pi-fff.schema.json\",\n  \"frecencyDbPath\": \"~/.local/share/pi/frecency\",\n  \"mode\": \"tools-only\"\n}","handlingStrategy":"validation","validationCode":"const CONFIG_KEYS = new Set([\"$schema\",\"mode\",\"frecencyDbPath\",\"historyDbPath\",\"enableFsRootScanning\",\"enableHomeDirScanning\",\"warnOnHomeDirScan\",\"followSymlinks\"]);\nconst parsed = JSON.parse(readFileSync(configPath, \"utf8\"));\nconst unknown = Object.keys(parsed).filter((k) => !CONFIG_KEYS.has(k));\nif (unknown.length > 0) {\n  throw new Error(`${configPath}: unknown option(s) ${unknown.map((k) => `\"${k}\"`).join(\", \")}`);\n}","typeGuard":"function isFffConfig(v: unknown): v is Record<string, unknown> & FffConfig {\n  if (typeof v !== \"object\" || v === null || Array.isArray(v)) return false;\n  const keys = new Set([\"$schema\",\"mode\",\"frecencyDbPath\",\"historyDbPath\",\"enableFsRootScanning\",\"enableHomeDirScanning\",\"warnOnHomeDirScan\",\"followSymlinks\"]);\n  return Object.keys(v).every((k) => keys.has(k));\n}","tryCatchPattern":"try {\n  const config = loadConfig(agentDir);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"unknown option\")) {\n    console.error(\"Fix or remove the unknown key in your pi-fff.json:\", err.message);\n    const config = {}; // fall back to defaults\n  } else {\n    throw err;\n  }\n}","preventionTips":["Validate pi-fff.json against the $schema or the FffConfig interface before deploying it","Copy option names exactly from the README/docs; keys are case-sensitive camelCase","After upgrading the package, diff your config against the current documented options","Keep the config minimal — only set options you have verified exist","Run a quick sanity script that JSON-parses the file and checks keys against CONFIG_KEYS before launching"],"tags":["config","validation","json","typo"],"backgroundTag":"unsupported-config-value","analyzedSha":"7f8537e70f0ea1210f9acbbfc4640141105cdc78","analyzedAt":"2026-09-10T07:26:53.407Z","contentChangedAt":"2026-09-10T07:26:53.407Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}