{"record":{"id":"013eaa88dba8d0c2","repo":"deepseek-ai/deepseek-harness","slug":"compactregion-start-seq-start-is-not-a-balance","errorCode":null,"errorMessage":"compactRegion: start seq ${start} is not a balanced boundary (would split a step's tool-call/result pair)","messagePattern":"compactRegion: start seq (.+?) is not a balanced boundary \\(would split a step's tool-call/result pair\\)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/compaction/compaction-basic/src/region.ts","lineNumber":328,"sourceCode":"    stage,\n  )\n}\n\n/** Validate one requested surface-position span before asynchronous work begins. */\nfunction validateSurfaceRegion(session: Session, start: number, end: number): SurfaceSelection {\n  const nodes = session.surface.nodes\n  const startIdx = nodes.indexOf(start)\n  const endIdx = nodes.indexOf(end)\n  if (startIdx === -1) throw new Error(`compactRegion: start seq ${start} not found in surface`)\n  if (endIdx === -1) throw new Error(`compactRegion: end seq ${end} not found in surface`)\n  if (startIdx > endIdx) {\n    throw new Error(\n      `compactRegion: start seq ${start} (position ${startIdx}) is after end seq ${end} (position ${endIdx}) on the surface`,\n    )\n  }\n  // oxlint-disable-next-line typescript/no-non-null-assertion\n  if (!toolPairingBalancedBefore(session, nodes[startIdx]!)) {\n    throw new Error(`compactRegion: start seq ${start} is not a balanced boundary (would split a step's tool-call/result pair)`)\n  }\n  // oxlint-disable-next-line typescript/no-non-null-assertion\n  if (!toolPairingBalancedAfter(session, nodes[endIdx]!)) {\n    throw new Error(`compactRegion: end seq ${end} is not a balanced boundary (would split a step, or the step is still open)`)\n  }\n\n  return { start, end, startIdx, endIdx, shadowedSeqs: nodes.slice(startIdx, endIdx + 1) }\n}\n\n/** Snapshot pricing and replay input for a validated surface range. */\nfunction prepareCompaction(\n  dependencies: RegionDependencies,\n  session: Session,\n  selection: SurfaceSelection,\n): PreparedCompaction {\n  const measurement = dependencies.meter.measure(session)\n  const selectedNodes = measurement.nodes.slice(selection.startIdx, selection.endIdx + 1)\n  if (selectedNodes.length !== selection.shadowedSeqs.length","sourceCodeStart":310,"sourceCodeEnd":346,"githubUrl":"https://github.com/deepseek-ai/deepseek-harness/blob/b150a551b8d465e31e418e1b2eaf5e79bbb7d28e/packages/compaction/compaction-basic/src/region.ts#L310-L346","documentation":"The cut immediately before `start` is crossed by an in-progress tool call: an assistant message containing tool-calls would be separated from its matching tool/result events by the replacement. Both span edges must be tool-pairing balanced (checked with toolPairingBalancedBefore/After from @deepseek-ai/dsh-compaction) so no step's call/result pair is split.","triggerScenarios":"Choosing `start` inside a multi-tool step — for example on a tool/result that follows an assistant message whose second tool-call is answered by a later node; deriving boundaries by token arithmetic without balance checks; cutting between an assistant tool-call message and its results.","commonSituations":"Agentic turns that issue parallel tool calls; hand-rolled range selection that ignores tool pairing; picking the 'oldest N tokens' boundary mid-step.","solutions":["Advance start forward to the next seq where toolPairingBalancedBefore(session, seq) returns true","Prefer step boundaries — the node right before an assistant or user message — as cut points","Let the engine select the range (compactNow / selectCompactableRange-style logic already backs off to balanced cuts)"],"exampleFix":"// before: arbitrary cut inside a step\nawait ctx.compaction.compactRegion(nodes[3]!, end, agent)\n\n// after: back off to a balanced cut\nimport { toolPairingBalancedBefore } from '@deepseek-ai/dsh-compaction'\nconst nodes = agent.session.surface.nodes\nlet i = 3\nwhile (!toolPairingBalancedBefore(agent.session, nodes[i]!)) i += 1\nawait ctx.compaction.compactRegion(nodes[i]!, end, agent)","handlingStrategy":"validation","validationCode":"import { toolPairingBalancedBefore } from '@deepseek-ai/dsh-compaction'\nif (!toolPairingBalancedBefore(agent.session, start)) {\n  // advance start to the next balanced cut before compacting\n  const nodes = agent.session.surface.nodes\n  let i = nodes.indexOf(start)\n  while (!toolPairingBalancedBefore(agent.session, nodes[i]!)) i += 1\n  start = nodes[i]!\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check toolPairingBalancedBefore on the start seq before every compactRegion call","Cut at step boundaries: right before an assistant or user message","Prefer engine-selected ranges (compactNow) which already back off to balanced cuts"],"tags":["compaction","tool-calls","surface","validation"],"backgroundTag":"unbalanced-tool-call-boundary","analyzedSha":"b150a551b8d465e31e418e1b2eaf5e79bbb7d28e","analyzedAt":"2026-08-24T18:12:29.105Z","schemaVersion":2},"datasetVersion":"2026-08-24T22:17:12.610Z"}