fix(agent): ignore Hermes INFO echoes that falsely fail completed runs (#5862) - #5864
Merged
Bohan-J merged 6 commits intoJul 24, 2026
Merged
Conversation
…oed stderr Hermes echoes whole conversation / tool-result records to stderr at `[INFO] root:` level as a single physical line tens of KB long. When that echoed content embeds unrelated skill-doc substrings — a bare "❌" bullet (matches acpTerminalErrorRe) and an "Error:"/"KeyError:" fragment (matches acpErrorDetailRe) far apart on the same line — the per-line sniffer treated the whole line as a terminal provider error and flipped a completed run to failed, storing an 18-87 KB blob as the task error. taskfailure.Classify then mislabeled it via bait substrings, yielding spurious provider_auth_or_access / context_overflow reasons. Cap the per-line length considered by the sniffer (acpMaxErrorLineLen). Genuine ACP provider-error lines are short (~150 bytes); a conversation echo is tens of KB, so an over-long line can never be a real error line. This keeps echoed content out of the sniffer while still admitting every real provider-error line. Fixes multica#5862 Co-authored-by: Cursor <cursoragent@cursor.com>
|
@YikaJ is attempting to deploy a commit to the IndexLabs Team on Vercel. A member of the Team first needs to authorize it. |
Production samples show short and long conversation records can reach stderr through Python's root logger. Ignore those INFO records before provider-error matching, while retaining genuine ERROR records and the size bound as defense in depth. Co-authored-by: Cursor <cursoragent@cursor.com>
Spell out that pollution failures already produced a successful final reply and were only flipped to failed at promotion time, while genuine ERROR root records remain terminal. Co-authored-by: Cursor <cursoragent@cursor.com>
…g runs Two boundary bugs behind the Hermes INFO over-match fix (multica-ai#5862): - A 4096-byte pre-match drop discarded any long stderr line before error matching, so a genuine long provider failure (e.g. HTTP 400 with a large {'detail': ...}) plus empty output was promoted to completed — the multica-ai#1952 regression. Length now only bounds the persisted summary, never whether a line is classified as an error. - The [INFO] root: filter matched only the first physical line, so a multi-line INFO echo whose continuation JSON embedded a terminal token still flipped a completed run to failed. The sniffer now tracks Python root-logger records and skips INFO/DEBUG records plus their continuation lines, while ERROR/WARNING/CRITICAL and bare provider-error lines match. Adds regression tests: multi-line INFO echo stays completed, a real [ERROR] root record after an INFO echo stays terminal, and a long real error with empty output still fails across all shared-sniffer providers. Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
Co-authored-by: multica-agent <github@multica.ai>
Collaborator
|
Thanks @YikaJ for the excellent diagnosis and the initial fix here 🙏 The pollution-vs-real-error framing, the production evidence, and the deterministic regression fixtures made this bug much easier to reason about — that's a high-quality report. Since this is a live-impacting bug, we pushed the remaining boundary fixes directly on top of your branch rather than round-tripping review, so we could land it quickly:
CI is green and the review is clear — merging now. Really appreciate the contribution! |
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?
Stops Multica from treating Hermes
[INFO] root:conversation/tool echoes as provider failures.Fixes #5862
Real error vs pollution error
This PR is specifically about pollution errors, not real Hermes/provider crashes.
failedfailedfailedbecause non-error stderr data matched error-looking tokens.completedfailedPollution is characterized by timing:
run-messagesalready contains a successful final reply.status=failed.erroris truncated conversation / tool / INFO JSON, not a short provider message.Production evidence
41–95bytes), e.g.AF_UNIX path too long,HTTP 400: ...,HTTP 429: ...,Request timed out.265–87,286bytes), contain conversation fingerprints (finish_reason,session_id,tool_call_id,[INFO] root:), and often start mid-JSON.265bytes.Root cause
Hermes writes conversation/tool JSON to stderr as:
Those INFO records are data. Their payload may contain
Error:,KeyError:,❌,HTTP 429, orAPI call failed. Because one JSON record is one physical line, unrelated payload fragments can satisfy both the sniffer capture filter and terminal condition. After #2323 removed the empty-output precondition, that false terminal match overrides a valid completed turn.Changes
[INFO] root:records before provider-error matching.acpMaxErrorLineLenas defense in depth for oversized echoes with an unexpected prefix.[ERROR] root:/ short provider-error behavior.[ERROR] root:records.How to test
Type of Change