fix(agent): repair malformed tool_call arguments before API send#12252
Closed
sirEven wants to merge 1 commit into
Closed
fix(agent): repair malformed tool_call arguments before API send#12252sirEven wants to merge 1 commit into
sirEven wants to merge 1 commit into
Conversation
Models like GLM-5.1 can produce invalid JSON in tool_call arguments
(truncated strings, trailing commas, Python None, empty strings). The
current code catches the exception from json.loads() but silently
passes, allowing the broken JSON through to the API — which rejects
it with HTTP 400 and crashes the entire session.
This patch adds a repair pipeline at the pre-send normalization point
(~L9179 in run_agent.py):
1. Empty/whitespace → '{}'
2. Python None literal → '{}'
3. Strip trailing commas before }/]
4. Auto-close unclosed { and [
5. Remove excess closing delimiters
6. Last resort: replace with '{}' (saves session, loses args)
All repairs are logged at WARNING level for observability.
The fix is model-agnostic — it only activates on the except branch
when json.loads() fails on tool_call arguments, so there is zero
overhead for valid JSON. It acts as a last line of defense before
the API request goes out, complementing upstream fixes that address
specific sources of corruption (compressor truncation, per-model
sanitizers, etc.).
Tested: live session with hermes chat, no 400 errors after patch.
Ollama proxy rejects broken args (400), accepts repaired args (200).
teknium1
pushed a commit
that referenced
this pull request
Apr 20, 2026
Cherry-picked from PR #12252 by @sirEven. Models like GLM-5.1 via Ollama can produce malformed tool_call arguments (truncated JSON, trailing commas, Python None). The existing except Exception: pass silently passes broken args to the API, which rejects them with HTTP 400, crashing the session. Adds a multi-stage repair pipeline at the pre-send normalization point: 1. Empty/whitespace-only → {} 2. Python None literal → {} 3. Strip trailing commas 4. Auto-close unclosed brackets 5. Remove excess closing delimiters 6. Last resort: replace with {} (logged at WARNING)
teknium1
added a commit
that referenced
this pull request
Apr 20, 2026
Follow-up for PR #12252 salvage: - Extract 75-line inline repair block to _repair_tool_call_arguments() module-level helper for testability and readability - Remove redundant 'import re as _re' (re already imported at line 33) - Bound the while-True excess-delimiter removal loop to 50 iterations - Add 17 tests covering all 6 repair stages - Add sirEven to AUTHOR_MAP in release.py
teknium1
pushed a commit
that referenced
this pull request
Apr 20, 2026
Cherry-picked from PR #12252 by @sirEven. Models like GLM-5.1 via Ollama can produce malformed tool_call arguments (truncated JSON, trailing commas, Python None). The existing except Exception: pass silently passes broken args to the API, which rejects them with HTTP 400, crashing the session. Adds a multi-stage repair pipeline at the pre-send normalization point: 1. Empty/whitespace-only → {} 2. Python None literal → {} 3. Strip trailing commas 4. Auto-close unclosed brackets 5. Remove excess closing delimiters 6. Last resort: replace with {} (logged at WARNING)
teknium1
added a commit
that referenced
this pull request
Apr 20, 2026
Follow-up for PR #12252 salvage: - Extract 75-line inline repair block to _repair_tool_call_arguments() module-level helper for testability and readability - Remove redundant 'import re as _re' (re already imported at line 33) - Bound the while-True excess-delimiter removal loop to 50 iterations - Add 17 tests covering all 6 repair stages - Add sirEven to AUTHOR_MAP in release.py
Contributor
ulasbilgen
pushed a commit
to ulasbilgen/hermes-adhd-agent
that referenced
this pull request
May 1, 2026
Cherry-picked from PR NousResearch#12252 by @sirEven. Models like GLM-5.1 via Ollama can produce malformed tool_call arguments (truncated JSON, trailing commas, Python None). The existing except Exception: pass silently passes broken args to the API, which rejects them with HTTP 400, crashing the session. Adds a multi-stage repair pipeline at the pre-send normalization point: 1. Empty/whitespace-only → {} 2. Python None literal → {} 3. Strip trailing commas 4. Auto-close unclosed brackets 5. Remove excess closing delimiters 6. Last resort: replace with {} (logged at WARNING)
ulasbilgen
pushed a commit
to ulasbilgen/hermes-adhd-agent
that referenced
this pull request
May 1, 2026
Follow-up for PR NousResearch#12252 salvage: - Extract 75-line inline repair block to _repair_tool_call_arguments() module-level helper for testability and readability - Remove redundant 'import re as _re' (re already imported at line 33) - Bound the while-True excess-delimiter removal loop to 50 iterations - Add 17 tests covering all 6 repair stages - Add sirEven to AUTHOR_MAP in release.py
aj-nt
pushed a commit
to aj-nt/hermes-agent
that referenced
this pull request
May 1, 2026
Cherry-picked from PR NousResearch#12252 by @sirEven. Models like GLM-5.1 via Ollama can produce malformed tool_call arguments (truncated JSON, trailing commas, Python None). The existing except Exception: pass silently passes broken args to the API, which rejects them with HTTP 400, crashing the session. Adds a multi-stage repair pipeline at the pre-send normalization point: 1. Empty/whitespace-only → {} 2. Python None literal → {} 3. Strip trailing commas 4. Auto-close unclosed brackets 5. Remove excess closing delimiters 6. Last resort: replace with {} (logged at WARNING)
aj-nt
pushed a commit
to aj-nt/hermes-agent
that referenced
this pull request
May 1, 2026
Follow-up for PR NousResearch#12252 salvage: - Extract 75-line inline repair block to _repair_tool_call_arguments() module-level helper for testability and readability - Remove redundant 'import re as _re' (re already imported at line 33) - Bound the while-True excess-delimiter removal loop to 50 iterations - Add 17 tests covering all 6 repair stages - Add sirEven to AUTHOR_MAP in release.py
Luminet2023
pushed a commit
to Luminet2023/hermes-agent
that referenced
this pull request
May 1, 2026
Cherry-picked from PR NousResearch#12252 by @sirEven. Models like GLM-5.1 via Ollama can produce malformed tool_call arguments (truncated JSON, trailing commas, Python None). The existing except Exception: pass silently passes broken args to the API, which rejects them with HTTP 400, crashing the session. Adds a multi-stage repair pipeline at the pre-send normalization point: 1. Empty/whitespace-only → {} 2. Python None literal → {} 3. Strip trailing commas 4. Auto-close unclosed brackets 5. Remove excess closing delimiters 6. Last resort: replace with {} (logged at WARNING)
Luminet2023
pushed a commit
to Luminet2023/hermes-agent
that referenced
this pull request
May 1, 2026
Follow-up for PR NousResearch#12252 salvage: - Extract 75-line inline repair block to _repair_tool_call_arguments() module-level helper for testability and readability - Remove redundant 'import re as _re' (re already imported at line 33) - Bound the while-True excess-delimiter removal loop to 50 iterations - Add 17 tests covering all 6 repair stages - Add sirEven to AUTHOR_MAP in release.py
02356abc
pushed a commit
to 02356abc/hermes-agent
that referenced
this pull request
May 14, 2026
Cherry-picked from PR NousResearch#12252 by @sirEven. Models like GLM-5.1 via Ollama can produce malformed tool_call arguments (truncated JSON, trailing commas, Python None). The existing except Exception: pass silently passes broken args to the API, which rejects them with HTTP 400, crashing the session. Adds a multi-stage repair pipeline at the pre-send normalization point: 1. Empty/whitespace-only → {} 2. Python None literal → {} 3. Strip trailing commas 4. Auto-close unclosed brackets 5. Remove excess closing delimiters 6. Last resort: replace with {} (logged at WARNING)
02356abc
pushed a commit
to 02356abc/hermes-agent
that referenced
this pull request
May 14, 2026
Follow-up for PR NousResearch#12252 salvage: - Extract 75-line inline repair block to _repair_tool_call_arguments() module-level helper for testability and readability - Remove redundant 'import re as _re' (re already imported at line 33) - Bound the while-True excess-delimiter removal loop to 50 iterations - Add 17 tests covering all 6 repair stages - Add sirEven to AUTHOR_MAP in release.py
gweeteve
pushed a commit
to gweeteve/hermes-agent
that referenced
this pull request
Jun 2, 2026
Cherry-picked from PR NousResearch#12252 by @sirEven. Models like GLM-5.1 via Ollama can produce malformed tool_call arguments (truncated JSON, trailing commas, Python None). The existing except Exception: pass silently passes broken args to the API, which rejects them with HTTP 400, crashing the session. Adds a multi-stage repair pipeline at the pre-send normalization point: 1. Empty/whitespace-only → {} 2. Python None literal → {} 3. Strip trailing commas 4. Auto-close unclosed brackets 5. Remove excess closing delimiters 6. Last resort: replace with {} (logged at WARNING)
gweeteve
pushed a commit
to gweeteve/hermes-agent
that referenced
this pull request
Jun 2, 2026
Follow-up for PR NousResearch#12252 salvage: - Extract 75-line inline repair block to _repair_tool_call_arguments() module-level helper for testability and readability - Remove redundant 'import re as _re' (re already imported at line 33) - Bound the while-True excess-delimiter removal loop to 50 iterations - Add 17 tests covering all 6 repair stages - Add sirEven to AUTHOR_MAP in release.py
Egavasyug
pushed a commit
to Egavasyug/hermes-agent
that referenced
this pull request
Jun 10, 2026
Cherry-picked from PR NousResearch#12252 by @sirEven. Models like GLM-5.1 via Ollama can produce malformed tool_call arguments (truncated JSON, trailing commas, Python None). The existing except Exception: pass silently passes broken args to the API, which rejects them with HTTP 400, crashing the session. Adds a multi-stage repair pipeline at the pre-send normalization point: 1. Empty/whitespace-only → {} 2. Python None literal → {} 3. Strip trailing commas 4. Auto-close unclosed brackets 5. Remove excess closing delimiters 6. Last resort: replace with {} (logged at WARNING)
Egavasyug
pushed a commit
to Egavasyug/hermes-agent
that referenced
this pull request
Jun 10, 2026
Follow-up for PR NousResearch#12252 salvage: - Extract 75-line inline repair block to _repair_tool_call_arguments() module-level helper for testability and readability - Remove redundant 'import re as _re' (re already imported at line 33) - Bound the while-True excess-delimiter removal loop to 50 iterations - Add 17 tests covering all 6 repair stages - Add sirEven to AUTHOR_MAP in release.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What does this PR do?
Adds a JSON repair pipeline at the pre-send normalization point in
run_agent.py(~L9179) to fix malformedtool_call.argumentsbefore they reach the API. Currently, whenjson.loads()fails inside theexcept Exception: passblock, the invalid JSON is silently passed through to the API — which rejects it with HTTP 400 "invalid tool call arguments", crashing the entire session.Related Issue
Type of Change
Changes Made
run_agent.py~L9179: Replacedexcept Exception: passwith a repair pipeline:"{}"Noneliteral →"{}"}or]{and["{}"(saves session, loses args — logged at WARNING)WARNINGlevel for observabilityHow to Test
Manual reproduction — in a session where the model generates truncated arguments:
except Exception: pass→ 400 error → session death spiralTested with live
hermes chatsession — zero 400 errors after patch. Confirmed Ollama proxy rejects broken args (400) and accepts repaired args (200).How this differs from existing PRs
This PR is complementary, not competing — it catches what slips through upstream. It operates at the pre-send normalization point, which is the last chance to fix broken args before the API call goes out. Even if compressor fixes (#11617, #11788) land, models can still produce malformed args at inference time (truncation, Python None, etc.) — this catches those cases.
Checklist