deepseek-ai/deepseek-harness · error
BasicCompactionConfig: modelPolicies must be an array
Error message
BasicCompactionConfig: modelPolicies must be an array
What it means
compaction-basic validates its whole plugin configuration eagerly at load time in resolveConfig(). modelPolicies holds exact provider/model override objects and must be an Array; resolveModelPolicies() rejects any other type before defaults are applied, so a malformed override table cannot silently match no policy.
Source
Thrown at packages/compaction/compaction-basic/src/config.ts:197
/** Reject a capacity-independent retention conflict at plugin load. */
function validateRatioRetention(
thresholdRatio: number,
retention: ResolvedRetention,
name: string,
): void {
if (retention.retainRatio !== undefined && retention.retainRatio >= thresholdRatio) {
throw new Error(
`${name}: retainRatio (${retention.retainRatio}) must be less than `
+ `the resolved thresholdRatio (${thresholdRatio})`,
)
}
}
/** Validate, detach, and reject duplicate exact-target policies. */
function resolveModelPolicies(configured: unknown): ModelCompactPolicyConfig[] {
if (configured === undefined) return []
if (!Array.isArray(configured)) {
throw new Error('BasicCompactionConfig: modelPolicies must be an array')
}
const seen = new Set<string>()
return configured.map((source: unknown, index) => {
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(View on GitHub (pinned to b150a551b8)
Solutions
- Rewrite modelPolicies as a YAML block list: each entry starts with '- ' and carries provider, model, and override fields
- If you keyed entries by provider (modelPolicies: { deepseek: { model: chat, ... } }), convert each group into list items that state both provider and model explicitly
- If no per-model overrides are needed, delete the modelPolicies key entirely — top-level defaults then apply to every routed model
- Type the field as ModelCompactPolicyConfig[] in programmatic config so the compiler rejects non-array shapes
Example fix
# cordis.yml — before (parses as an object)
plugins:
'@deepseek-ai/dsh-compaction-basic':
config:
modelPolicies:
deepseek:
model: deepseek-chat
maxTokens: 16384
# after (array of exact-target overrides)
plugins:
'@deepseek-ai/dsh-compaction-basic':
config:
modelPolicies:
- provider: deepseek
model: deepseek-chat
maxTokens: 16384 Defensive patterns
Strategy: validation
Validate before calling
// Pre-flight before booting the plugin:
if (config.modelPolicies !== undefined && !Array.isArray(config.modelPolicies)) {
throw new TypeError(
`modelPolicies must be an array, got ${typeof config.modelPolicies}`,
)
}
const resolved = resolveConfig(config) Try / catch
try {
resolveConfig(config)
} catch (err) {
// Static config failure: report the source and stop; never retry —
// the same config produces the same throw.
throw new Error(
`cordis.yml compaction-basic config invalid: ${(err as Error).message}`,
{ cause: err },
)
} Prevention
- Type modelPolicies as ModelCompactPolicyConfig[] in any code that builds the config
- In YAML, start every entry with '- provider:' and confirm the block parses as a sequence, not a mapping
- Run the repo's config verification (verify-cordis-config / doc-sync gates) after editing cordis.yml
When it happens
Trigger: A cordis.yml compaction-basic config block (or a programmatic resolveConfig(config) call) supplies modelPolicies as a YAML/JSON mapping instead of a sequence (e.g. modelPolicies: { deepseek: ... }), a scalar, or a single bare object. YAML is the usual culprit: keyed entries under modelPolicies: parse as an object, not a list.
Common situations: Hand-editing cordis.yml and keying policies by provider name (natural for maps elsewhere in the file); copy-pasting a single { provider, model } object without wrapping it in a list; config pipelines re-serializing the array as an object.
Related errors
- ${name} must be an object
- 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/1ed021803bc2c1eb.
Report an issue: GitHub.