deepseek-ai/deepseek-harness · error

${name}: summarizationProvider and summarizationModel must b

Error message

${name}: summarizationProvider and summarizationModel must be set together as an empty or non-empty pair

What it means

The summarization target is managed as an inseparable pair per scope: omit both keys to inherit, set both to '' to explicitly clear, or set both to non-empty strings to replace. Any half-set or mixed-emptiness combination is rejected so resolveTargetPolicy()'s 'override ?? default' merge can never produce a provider-less model or a model-less provider.

Source

Thrown at packages/compaction/compaction-basic/src/config.ts:270

}

/** Require one scope to omit, clear, or replace the summarization target as a pair. */
function validateSummarizationPair(
  config: CompactionPolicyConfig | Record<string, unknown>,
  name: string,
): void {
  const provider = config.summarizationProvider
  const model = config.summarizationModel
  if (provider !== undefined && typeof provider !== 'string') {
    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 {

View on GitHub (pinned to b150a551b8)

Solutions

  1. To set a summarization target, provide both summarizationProvider and summarizationModel as non-empty strings
  2. To clear the target for a modelPolicies entry, set both fields to ''
  3. To inherit the effective setting, remove both keys

Example fix

# before — half-set pair
summarizationProvider: deepseek

# after — complete pair
summarizationProvider: deepseek
summarizationModel: deepseek-chat
Defensive patterns

Strategy: validation

Validate before calling

for (const scope of [config, ...(config.modelPolicies ?? [])]) {
  const p = scope.summarizationProvider
  const m = scope.summarizationModel
  const pairOk = p === undefined && m === undefined
    || (p !== undefined && m !== undefined && (p.length === 0) === (m.length === 0))
  if (!pairOk) throw new Error('summarizationProvider and summarizationModel must be set together')
}
resolveConfig(config)

Try / catch

try {
  resolveConfig(config)
} catch (err) {
  if ((err as Error).message.includes('set together')) {
    throw new Error(
      'summarization pair incomplete: set both fields non-empty, set both to empty strings to clear, or remove both',
      { cause: err },
    )
  }
  throw err
}

Prevention

When it happens

Trigger: Top level or a modelPolicies entry sets exactly one of summarizationProvider/summarizationModel, or sets one to '' and the other to a non-empty string. Both undefined (inherit) and both '' (explicit clear) pass.

Common situations: Assuming the model alone identifies the target because only one provider is configured; trying to disable summarization by blanking just one field; copy-paste that drops one of the two lines.

Related errors


AI-assisted analysis of deepseek-ai/deepseek-harness@b150a551b8 (2026-08-24). Data as JSON: /api/errors/57314f7df7f6ae64. Report an issue: GitHub.