deepseek-ai/deepseek-harness · error
${name} must be an object
Error message
${name} must be an object What it means
Every element of the modelPolicies array is validated by assertModelPolicy() before use. An element that is not a plain object — a string, number, boolean, null, or nested array — fails the '${name} must be an object' check, where name is 'BasicCompactionConfig: modelPolicies[<index>]' pointing at the exact bad element.
Source
Thrown at packages/compaction/compaction-basic/src/config.ts:219
const name = `BasicCompactionConfig: modelPolicies[${index}]`
assertModelPolicy(source, name)
const key = `${source.provider}\u0000${source.model}`
if (seen.has(key)) {
throw new Error(
`BasicCompactionConfig: duplicate model policy for ${source.provider}/${source.model}`,
)
}
seen.add(key)
return { ...source }
})
}
/** Validate one untrusted exact-target override and narrow its public type. */
function assertModelPolicy(
source: unknown,
name: string,
): asserts source is ModelCompactPolicyConfig {
if (!isUnknownRecord(source)) throw new Error(`${name} must be an object`)
validateKeys(source, MODEL_POLICY_KEYS, name)
assertNonEmptyString(`${name}.provider`, source.provider)
assertNonEmptyString(`${name}.model`, source.model)
validatePolicy(source, name)
}
/** Validate the fields common to defaults and exact-target partial overrides. */
function validatePolicy(
config: CompactionPolicyConfig | Record<string, unknown>,
name: string,
): void {
const thresholdRatio = config.thresholdRatio
const retainRatio = config.retainRatio
const retainTokens = config.retainTokens
const maxTokens = config.maxTokens
const compactionRetries = config.compactionRetries
const maxOverflowRetries = config.maxOverflowRetries
if (thresholdRatio !== undefined) assertRatio(`${name}.thresholdRatio`, thresholdRatio)View on GitHub (pinned to b150a551b8)
Solutions
- Make each list item an object with explicit provider and model fields plus optional policy fields
- Remove null or placeholder entries from the list
- Check YAML indentation: every item under modelPolicies must start with '- provider:'
Example fix
# before — shorthand string entries
modelPolicies:
- deepseek/deepseek-chat
- deepseek/deepseek-reasoner
# after — object entries
modelPolicies:
- provider: deepseek
model: deepseek-chat
- provider: deepseek
model: deepseek-reasoner Defensive patterns
Strategy: type-guard
Type guard
function isModelPolicyCandidate(v: unknown): v is Record<string, unknown> {
return typeof v === 'object' && v !== null && !Array.isArray(v)
}
// usage: (config.modelPolicies ?? []).every(isModelPolicyCandidate) Try / catch
try {
resolveConfig(config)
} catch (err) {
const idx = (err as Error).message.match(/modelPolicies\[(\d+)\] must be an object/)?.[1]
if (idx !== undefined) {
throw new Error(
`modelPolicies[${idx}] is not an object: ${JSON.stringify(config.modelPolicies?.[+idx])} — use { provider, model, ...policy }`,
{ cause: err },
)
}
throw err
} Prevention
- Never use 'provider/model' shorthand strings — the schema requires both as object fields
- Lint YAML so every modelPolicies item starts with '- provider:'
- Type the array in TypeScript so string entries fail to compile
When it happens
Trigger: A list item that is a shorthand string (e.g. '- deepseek/deepseek-chat'), a bare scalar ('- 16384'), a null placeholder ('- ~' or an empty '- '), or a nested sequence. Only mapping items ('- provider: x') pass.
Common situations: Trying a compact 'provider/model' string syntax the plugin does not support; YAML indentation that puts a value on its own list item; JSON configs where an entry got replaced by its model name string.
Related errors
- BasicCompactionConfig: modelPolicies must be an array
- BasicCompactionConfig: auto must be a boolean
- BasicCompactionConfig: duplicate model policy for ${source.p
- ${name}.summarizationProvider must be a string
- ${name}.summarizationModel must be a string
AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24).
Data as JSON: /api/errors/845d8826a3c1e97a.
Report an issue: GitHub.