deepseek-ai/deepseek-harness · error
${name}: unknown key "${key}"
Error message
${name}: unknown key "${key}" What it means
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).
Source
Thrown at packages/compaction/compaction-basic/src/config.ts:280
throw new Error(`${name}.summarizationProvider must be a string`)
}
if (model !== undefined && typeof model !== 'string') {
throw new Error(`${name}.summarizationModel must be a string`)
}
if (provider === undefined && model === undefined) return
if (provider === undefined || model === undefined
|| (provider.length === 0) !== (model.length === 0)) {
throw new Error(
`${name}: summarizationProvider and summarizationModel must be set together `
+ 'as an empty or non-empty pair',
)
}
}
/** Reject stale or misspelled keys before defaults can hide them. */
function validateKeys(config: object, keys: ReadonlySet<string>, name: string): void {
for (const key of Object.keys(config)) {
if (!keys.has(key)) throw new Error(`${name}: unknown key "${key}"`)
}
}
function isUnknownRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value)
}
function assertNonEmptyString(name: string, value: unknown): asserts value is string {
if (typeof value !== 'string' || value.length === 0) {
throw new Error(`${name} must be a non-empty string`)
}
}
function assertPositiveInteger(name: string, value: unknown): asserts value is number {
if (typeof value !== 'number' || !Number.isInteger(value) || value <= 0) {
throw new Error(`${name} (${String(value)}) must be a positive integer`)
}
}View on GitHub (pinned to b150a551b8)
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
Example fix
# before
modelPolicies:
- provider: deepseek
model: deepseek-chat
maxToken: 16384 # typo: unknown key
auto: false # wrong scope: top-level only
# after
auto: false
modelPolicies:
- provider: deepseek
model: deepseek-chat
maxTokens: 16384 Defensive patterns
Strategy: validation
Validate before calling
const POLICY_KEYS = new Set([
'thresholdRatio', 'retainRatio', 'retainTokens',
'summarizationProvider', 'summarizationModel',
'maxTokens', 'compactionRetries', 'maxOverflowRetries',
])
const TOP_KEYS = new Set([...POLICY_KEYS, 'modelPolicies', 'auto'])
const ENTRY_KEYS = new Set([...POLICY_KEYS, 'provider', 'model'])
function checkKeys(obj: object, allowed: Set<string>, where: string) {
for (const k of Object.keys(obj)) {
if (!allowed.has(k)) throw new Error(`${where}: unknown key ${k}`)
}
}
checkKeys(config, TOP_KEYS, 'config')
for (const [i, e] of (config.modelPolicies ?? []).entries()) {
checkKeys(e, ENTRY_KEYS, `modelPolicies[${i}]`)
} Try / catch
try {
resolveConfig(config)
} catch (err) {
const key = (err as Error).message.match(/unknown key "(.+?)"/)?.[1]
if (key !== undefined) {
throw new Error(
`config key ${key} is misspelled, stale, or in the wrong scope — compare with the allowed key set`,
{ cause: err },
)
}
throw err
} Prevention
- 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
When it happens
Trigger: 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.
Common situations: Version upgrades that renamed keys; copy-paste between different plugins' config blocks; editor autocompletion inserting a plausible-but-wrong field name.
Related errors
- BasicCompactionConfig: auto must be a boolean
- BasicCompactionConfig: ${policy.target.provider}/${policy.ta
- ${name}: retainRatio (${retention.retainRatio}) must be less
- BasicCompactionConfig: modelPolicies must be an array
- BasicCompactionConfig: duplicate model policy for ${source.p
AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24).
Data as JSON: /api/errors/a58d75716af02e4f.
Report an issue: GitHub.