{"record":{"id":"a58d75716af02e4f","repo":"deepseek-ai/deepseek-harness","slug":"name-unknown-key-key","errorCode":null,"errorMessage":"${name}: unknown key \"${key}\"","messagePattern":"(.+?): unknown key \"(.+?)\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"packages/compaction/compaction-basic/src/config.ts","lineNumber":280,"sourceCode":"    throw new Error(`${name}.summarizationProvider must be a string`)\n  }\n  if (model !== undefined && typeof model !== 'string') {\n    throw new Error(`${name}.summarizationModel must be a string`)\n  }\n  if (provider === undefined && model === undefined) return\n  if (provider === undefined || model === undefined\n    || (provider.length === 0) !== (model.length === 0)) {\n    throw new Error(\n      `${name}: summarizationProvider and summarizationModel must be set together `\n      + 'as an empty or non-empty pair',\n    )\n  }\n}\n\n/** Reject stale or misspelled keys before defaults can hide them. */\nfunction validateKeys(config: object, keys: ReadonlySet<string>, name: string): void {\n  for (const key of Object.keys(config)) {\n    if (!keys.has(key)) throw new Error(`${name}: unknown key \"${key}\"`)\n  }\n}\n\nfunction isUnknownRecord(value: unknown): value is Record<string, unknown> {\n  return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction assertNonEmptyString(name: string, value: unknown): asserts value is string {\n  if (typeof value !== 'string' || value.length === 0) {\n    throw new Error(`${name} must be a non-empty string`)\n  }\n}\n\nfunction assertPositiveInteger(name: string, value: unknown): asserts value is number {\n  if (typeof value !== 'number' || !Number.isInteger(value) || value <= 0) {\n    throw new Error(`${name} (${String(value)}) must be a positive integer`)\n  }\n}","sourceCodeStart":262,"sourceCodeEnd":298,"githubUrl":"https://github.com/deepseek-ai/deepseek-harness/blob/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e/packages/compaction/compaction-basic/src/config.ts#L262-L298","documentation":"Configuration uses strict unknown-key rejection: validateKeys() throws on the first key outside the allowed set, before defaults can hide the mistake. Top level accepts thresholdRatio, retainRatio, retainTokens, summarizationProvider, summarizationModel, maxTokens, compactionRetries, maxOverflowRetries, modelPolicies, and auto; a modelPolicies entry accepts provider and model plus the eight policy fields (not auto).","triggerScenarios":"A misspelled key (retainToken, thresoldRatio, summarisationModel), a stale key from another version, or a key nested in the wrong scope: 'auto' inside a modelPolicies entry, or 'modelPolicies' nested inside an entry.","commonSituations":"Version upgrades that renamed keys; copy-paste between different plugins' config blocks; editor autocompletion inserting a plausible-but-wrong field name.","solutions":["Fix the rejected key named in the message against the allowed set for that scope (e.g. maxToken to maxTokens)","Move scope-bound keys to the correct block: auto and modelPolicies are top-level; provider and model belong to entries","Delete keys the current version does not support instead of leaving them in place"],"exampleFix":"# before\nmodelPolicies:\n  - provider: deepseek\n    model: deepseek-chat\n    maxToken: 16384   # typo: unknown key\n    auto: false       # wrong scope: top-level only\n\n# after\nauto: false\nmodelPolicies:\n  - provider: deepseek\n    model: deepseek-chat\n    maxTokens: 16384","handlingStrategy":"validation","validationCode":"const POLICY_KEYS = new Set([\n  'thresholdRatio', 'retainRatio', 'retainTokens',\n  'summarizationProvider', 'summarizationModel',\n  'maxTokens', 'compactionRetries', 'maxOverflowRetries',\n])\nconst TOP_KEYS = new Set([...POLICY_KEYS, 'modelPolicies', 'auto'])\nconst ENTRY_KEYS = new Set([...POLICY_KEYS, 'provider', 'model'])\n\nfunction checkKeys(obj: object, allowed: Set<string>, where: string) {\n  for (const k of Object.keys(obj)) {\n    if (!allowed.has(k)) throw new Error(`${where}: unknown key ${k}`)\n  }\n}\n\ncheckKeys(config, TOP_KEYS, 'config')\nfor (const [i, e] of (config.modelPolicies ?? []).entries()) {\n  checkKeys(e, ENTRY_KEYS, `modelPolicies[${i}]`)\n}","typeGuard":null,"tryCatchPattern":"try {\n  resolveConfig(config)\n} catch (err) {\n  const key = (err as Error).message.match(/unknown key \"(.+?)\"/)?.[1]\n  if (key !== undefined) {\n    throw new Error(\n      `config key ${key} is misspelled, stale, or in the wrong scope — compare with the allowed key set`,\n      { cause: err },\n    )\n  }\n  throw err\n}","preventionTips":["Paste the allowed key list as a comment above the config block","After version upgrades, diff your cordis.yml keys against the plugin README supported keys","Run the repo's verify-cordis-config gate in CI so typos fail before boot"],"tags":["config","validation","typo","unknown-key","compaction"],"backgroundTag":"unknown-config-key","analyzedSha":"b150a551b8d465e31e418e1b2eaf5e79bbb7d28e","analyzedAt":"2026-08-24T18:12:29.105Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}