langchain-ai/deepagents · error · ValueError
DiffStats counts cannot be negative, got additions={self.add
Error message
DiffStats counts cannot be negative, got additions={self.additions}, deletions={self.deletions} What it means
`DiffStats.__post_init__` validates that `additions` and `deletions` are non-negative. A negative count means the caller computed diff statistics incorrectly (e.g. mis-parsed hunk headers like `@@ -1,3 +1,-2 @@` or subtracted counts in the wrong order). The library throws immediately rather than propagating nonsense metrics into UI or reporting code.
Source
Thrown at libs/code/deepagents_code/diff_utils.py:91
additions: int
deletions: int
def __post_init__(self) -> None:
"""Reject negative counts.
Both in-repo producers derive from `difflib`, so this only guards direct
construction — but the type is public and reaches a delete prompt, where
the number gates destroying a file.
Raises:
ValueError: If either count is negative.
"""
if self.additions < 0 or self.deletions < 0:
msg = (
f"DiffStats counts cannot be negative, got additions="
f"{self.additions}, deletions={self.deletions}"
)
raise ValueError(msg)
def split_diff_lines(diff: str) -> list[str]:
r"""Split a unified diff back into the lines it was assembled from.
Deliberately not `splitlines()`. Every diff reaching this function is
`"\n"`-joined from lines that themselves came from `splitlines()` or
`split("\n")`, so no element can contain a line boundary and `"\n"` is the
exact inverse. `splitlines()` also breaks on `\r`, `\v`, `\f`, U+2028,
U+2029 and U+0085, which splits a single diff line into fragments. The tail
fragment carries no `+`/`-` marker, so it would render as an unmarked note —
on the approval prompt that means changed content shown as neutral metadata.
Check any new producer against that invariant rather than against a list of
the current ones.
Args:
diff: Unified diff string.View on GitHub (pinned to a1af029e6e)
Solutions
- Fix the computing code so counts are clamped to >= 0 (e.g. `max(0, parsed_count)`).
- Validate the diff text before parsing: hunk headers must match `@@ -a,b +c,d @@` with non-negative values.
- Log the raw diff alongside the error to locate the malformed hunk that produced the negative number.
Example fix
// before stats = DiffStats(additions=old_count - new_count, deletions=0) // after stats = DiffStats(additions=max(0, new_count - old_count), deletions=max(0, old_count - new_count))
Defensive patterns
Strategy: validation
Validate before calling
def make_diff_stats(additions: int, deletions: int) -> DiffStats:
if additions < 0 or deletions < 0:
raise ValueError(f"bad diff counts: +{additions} -{deletions}")
return DiffStats(additions=additions, deletions=deletions) Type guard
def has_valid_diff_counts(s: object) -> bool:
return isinstance(s, DiffStats) and s.additions >= 0 and s.deletions >= 0 Try / catch
try:
stats = DiffStats(additions=add, deletions=dele)
except ValueError as exc:
logger.error("Diff parsing produced invalid counts: %s", exc)
stats = DiffStats(additions=0, deletions=0) Prevention
- Clamp parsed hunk-header values with max(0, value).
- Test your diff parser against truncated and hand-edited diffs.
- Parse additions and deletions independently; never derive one by subtracting the other.
When it happens
Trigger: Constructing `DiffStats(additions=..., deletions=...)` with either field negative — usually counts derived from malformed diff hunk headers or by subtracting a larger value from a smaller one.
Common situations: Parsing truncated or hand-edited unified diffs; a hunk-header regex capturing a stray minus sign; off-by-one arithmetic when computing net changes; feeding a custom diff format the parser was not designed for.
Related errors
- shell_allow_list must be None or non-empty
- goal application requires a non-empty objective and rubric
- Provider name cannot be empty
- API key cannot be empty
- suffix must be empty or a short extension such as .md
AI-assisted analysis of langchain-ai/deepagents@a1af029e6e (2026-08-29).
Data as JSON: /api/errors/858c257446cfdfad.
Report an issue: GitHub.