fix(matrix): stop classifying auth errors by substring match - #57375
fix(matrix): stop classifying auth errors by substring match#57375gmoranxyz wants to merge 1 commit into
Conversation
The sync loop's permanent-auth-error detection matched "401"/"403"/ "unauthorized"/"forbidden" against str(exc), including the raw body of non-Matrix error responses. A transient Umbrel proxy error page (returned when Synapse briefly restarted) contained an SVG path coordinate with the digits "401" in it, which falsely tripped the permanent-auth-error path and permanently killed the sync loop on a purely transient connection blip. Use the structured http_status/errcode from mautrix's own exception types instead, which are only set for real Matrix API error responses.
Related to the Matrix permanent-auth classifier cluster: #56532 (issue), #56547 and #57150 (fix the false-negative — loop won't stop on 'Unable to introspect the access token'). This PR fixes the opposite false-positive — the loop wrongly stopping on a transient proxy error page that coincidentally contained '401' — by replacing substring matching on |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for replacing text-based classification with the SDK's structured error data. The false-positive is present on current main at plugins/platforms/matrix/adapter.py:2335-2346, and the patch applies cleanly.
Problems
tests/gateway/test_ws_auth_retry.py:155-188currently requires a plainRuntimeError("HTTP 401 Unauthorized")to stop after one attempt. With this patch it has neitherhttp_statusnorerrcode, so it reaches the retry branch forever. Update that test to the structured SDK contract and add the proxy-body false-positive regression.- The new errcode list omits
M_UNAUTHORIZED; mautrix 0.21.0 declares it at upstreammautrix/errors/request.py:188-190.
Suggested changes
- Cover both a structured Matrix auth exception that stops and an unstructured exception whose text contains
401that retries/recoveres. - Add
M_UNAUTHORIZEDto the errcode classification if errcode is intended to be independently terminal.
Automated hermes-sweeper review.
| http_status = getattr(exc, "http_status", None) | ||
| errcode = (getattr(exc, "errcode", None) or "").upper() | ||
| if http_status in (401, 403) or errcode in ( | ||
| "M_UNKNOWN_TOKEN", |
There was a problem hiding this comment.
Please include M_UNAUTHORIZED in this structured errcode set. The pinned mautrix 0.21.0 exposes it as a standard request error (mautrix/errors/request.py:188-190), so errcode-based classification otherwise omits one of the auth codes the old text matcher covered.
GottZ
left a comment
There was a problem hiding this comment.
This was generated by AI during triage.
Summary
Two open PRs address the same Matrix sync-loop false positive: #57375 removes exception-text matching in favor of structured mautrix status/errcode fields, while #66878 adds a dedicated classifier, preserves bounded fallback parsing for unstructured errors, and includes direct classifier tests for the reported 502/SVG case.
Related pull requests
- #57375
related— (+11/-7) — keep open pending consolidation: the diff directly removes the unsafe substring match that caused transient proxy bodies containing401/403to halt sync, but it lacks regression coverage, breaks the existing plain-RuntimeErrorexpectation, and omitsM_UNAUTHORIZED, as identified by the keep_open review on #57375. - #66878
duplicate— (+104/-8) — preferred consolidation base: the diff fixes the same root cause while covering structured statuses, leading textual statuses, and the reported 502/SVG payload; consistent with the keep_open review on #66878, it still needs an async_sync_loopregression proving retry-versus-return behavior, and salvage should explicitly decide whether retaining bounded unstructured-text fallback is acceptable.
Duplicates
#57375 and #66878 substantially duplicate the replacement of broad str(exc) substring classification for Matrix permanent-auth failures; #66878 is the broader implementation and test-bearing variant.
Suggested consolidation
Merge #66878 after adding the requested loop-level regression and explicitly resolving the bounded unstructured-text fallback policy; also include M_UNAUTHORIZED if errcode alone is terminal. Then close #57375 as superseded by #66878, carrying over its stricter structured-data rationale rather than merging both competing classifiers.
Complex graph
flowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
subgraph Dup57375 ["PRs duplicating each other"]
P57375["PR #57375 (open)"]
P66878["PR #66878 (open)"]
end
class P57375 open
class P66878 open
class P57375 target
click P57375 "https://github.com/NousResearch/hermes-agent/pull/57375"
click P66878 "https://github.com/NousResearch/hermes-agent/pull/66878"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label).
Cross-PR triage: Reviewed 2 pull requests and 0 issues in this complex. Each diff was read against this issue; Assessment working set: 8 kB of PR diffs, 3 kB of issue/PR text, 3 kB of discussion (4 comments), 0 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.
Summary
"401"/"403"/"unauthorized"/"forbidden"againststr(exc), including the raw body of non-Matrix error responses.http_status/errcodeattributes that mautrix's own exception types (MatrixRequestErrorand subclasses) set for genuine Matrix API error responses, instead of substring-matching arbitrary exception text.Test plan
python -m py_compile plugins/platforms/matrix/adapter.pyscripts/run_tests.sh tests/for matrix platform coverage, if any exists