hermes - ✅(Solved) Fix ssl.SSLCertVerificationError misclassified as local validation error [3 pull requests, 1 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
NousResearch/hermes-agent#14367Fetched 2026-04-24 06:17:38
View on GitHub
Comments
0
Participants
1
Timeline
6
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×3labeled ×3

Error Message

The error classifier correctly maps SSLCertVerificationError to FailoverReason.timeout, retryable=True (its type name is in _TRANSPORT_ERROR_TYPES), but the inline isinstance check overrides that. Low. Cert errors rarely reach the API response handler — they are typically caught at the connection layer before the except Exception as api_error block. But if a provider returns a cert error mid-stream (e.g., TLS renegotiation failure after the HTTP request is sent), this would cause an unnecessary abort.

Fix Action

Fix

Add ssl.SSLCertVerificationError (or its parent ssl.SSLError) to the exclusion list in is_local_validation_error, alongside the existing UnicodeError and json.JSONDecodeError exclusions from #14366.

PR fix notes

PR #14374: fix(agent): retry TLS certificate transport errors

Description (problem / solution / changelog)

Root cause

ssl.SSLCertVerificationError inherits from ValueError, so the inline local-validation guard treated TLS certificate failures as non-retryable request-shaping bugs. Those failures are provider transport errors and should stay on the normal retry/failover path.

Closes #14367.

Fix

  • Add a small _is_local_validation_error() helper for the request-shaping guard.
  • Exclude ssl.SSLError from local-validation classification, which covers SSLCertVerificationError and related TLS transport failures.
  • Add regression coverage proving certificate errors are not treated as local validation while ordinary ValueError/TypeError still are.

Tests

  • uv run --frozen --python 3.11 --extra dev pytest -o addopts= tests/run_agent/test_run_agent.py::test_ssl_cert_verification_error_is_not_local_validation tests/run_agent/test_run_agent.py::test_request_shaping_errors_are_local_validation tests/run_agent/test_run_agent.py::test_unicode_encode_error_is_not_local_validation -q -> 4 passed
  • uv run --frozen --python 3.11 --extra dev pytest -o addopts= tests/agent/test_error_classifier.py -q -> 111 passed
  • uv run --frozen --python 3.11 --extra dev pytest -o addopts= tests/run_agent/test_run_agent.py -q -> 297 passed
  • git diff --check

Changed files

  • run_agent.py (modified, +10/-4)
  • tests/run_agent/test_run_agent.py (modified, +20/-0)

PR #14434: fix(agent): exclude ssl.SSLError from local validation error check

Description (problem / solution / changelog)

What does this PR do?

ssl.SSLCertVerificationError inherits from SSLError → OSError → ValueError. The is_local_validation_error guard in run_agent.py caught it via isinstance(api_error, ValueError) and triggered a non-retryable abort — even though the error classifier already returns retryable=True for all OSError subclasses (transport heuristic, step 7).

The inline isinstance check fires before classified.retryable is consulted, so the classifier's correct verdict is overridden. Fix: add ssl.SSLError to the exclusion tuple alongside the existing UnicodeEncodeError, mirroring the same pattern already in place.

Related Issue

Fixes #14367

Type of Change

  • 🐛 Bug fix (non-breaking change that fixes an issue)
  • ✨ New feature (non-breaking change that adds functionality)
  • 🔒 Security fix
  • 📝 Documentation update
  • ✅ Tests (adding or improving test coverage)
  • ♻️ Refactor (no behavior change)
  • 🎯 New skill (bundled or hub)

Changes Made

  • run_agent.py: add import ssl (stdlib, no new dependency); extend exclusion tuple to (UnicodeEncodeError, ssl.SSLError) with inline comment explaining the MRO
  • tests/run_agent/test_14367_ssl_local_validation.py: new test file covering the reported case (SSLCertVerificationError), the parent class (ssl.SSLError), the MRO prerequisite, the preserved UnicodeEncodeError exclusion, and regression checks that plain ValueError/TypeError remain local errors

How to Test

  1. Confirm the MRO that caused the bug:
    import ssl
    e = ssl.SSLCertVerificationError("cert error")
    print(isinstance(e, ValueError))  # True — this was the root cause
  2. Run the new tests:
    pytest tests/run_agent/test_14367_ssl_local_validation.py -v
  3. All 7 tests should pass.

Checklist

Code

  • I've read the Contributing Guide
  • My commit messages follow Conventional Commits (fix(scope):, feat(scope):, etc.)
  • I searched for existing PRs to make sure this isn't a duplicate
  • My PR contains only changes related to this fix/feature (no unrelated commits)
  • I've run pytest tests/ -q and all tests pass
  • I've added tests for my changes (required for bug fixes, strongly encouraged for features)
  • I've tested on my platform: macOS

Documentation & Housekeeping

  • I've updated relevant documentation (README, docs/, docstrings) — or N/A
  • I've updated cli-config.yaml.example if I added/changed config keys — or N/A
  • I've updated CONTRIBUTING.md or AGENTS.md if I changed architecture or workflows — or N/A
  • I've considered cross-platform impact (Windows, macOS) per the compatibility guide — or N/A
  • I've updated tool descriptions/schemas if I changed tool behavior — or N/A

Changed files

  • run_agent.py (modified, +2/-1)
  • tests/run_agent/test_14367_ssl_local_validation.py (added, +77/-0)

PR #14445: fix(agent): exclude ssl.SSLError from is_local_validation_error to prevent non-retryable abort

Description (problem / solution / changelog)

Problem

Fixes #14367.

ssl.SSLError (and its subclass ssl.SSLCertVerificationError) inherits from both OSError and ValueError via Python's MRO:

ssl.SSLCertVerificationError
  └─ ssl.SSLError
       ├─ OSError
       └─ (via adapter) ValueError

The is_local_validation_error check at run_agent.py ~line 10681:

is_local_validation_error = (
    isinstance(api_error, (ValueError, TypeError))
    and not isinstance(api_error, UnicodeEncodeError)
)

…catches ssl.SSLCertVerificationError as a ValueError, marking it non-retryable and triggering an immediate abort.

The error classifier already maps SSLCertVerificationError to FailoverReason.timeout, retryable=True (its type name appears in _TRANSPORT_ERROR_TYPES), but the inline isinstance guard overrides that mapping before the classifier result is checked.

Result: A TLS transport error causes an unnecessary session abort instead of retrying or failing over to a backup provider.

Fix

Add ssl.SSLError to the exclusion list alongside the existing UnicodeEncodeError carve-out, and import ssl at the top of run_agent.py:

import ssl
# …
is_local_validation_error = (
    isinstance(api_error, (ValueError, TypeError))
    and not isinstance(api_error, UnicodeEncodeError)
    and not isinstance(api_error, ssl.SSLError)   # ← new
)

Verification

import ssl
e = ssl.SSLCertVerificationError("certificate verify failed")

# Before fix:
isinstance(e, (ValueError, TypeError))  # True  → flagged as programming bug

# After fix:
is_local = (
    isinstance(e, (ValueError, TypeError))
    and not isinstance(e, UnicodeEncodeError)
    and not isinstance(e, ssl.SSLError)
)
assert is_local is False  # ✅ falls through to classifier's retryable path

Changed files

  • run_agent.py (modified, +9/-0)

Code Example

import ssl
e = ssl.SSLCertVerificationError("certificate verify failed")
# is_local_validation_error logic:
isinstance(e, (ValueError, TypeError))  # True — it IS a ValueError via MRO
# So it gets flagged as non-retryable, even though classifier says retryable
RAW_BUFFERClick to expand / collapse

Bug

ssl.SSLCertVerificationError inherits from both OSError and ValueError (via Python MRO). The is_local_validation_error check in run_agent.py (~line 10691) catches it as isinstance(api_error, ValueError) and triggers a non-retryable abort — but a cert verification failure from a provider connection is a transport issue, not a local programming bug.

The error classifier correctly maps SSLCertVerificationError to FailoverReason.timeout, retryable=True (its type name is in _TRANSPORT_ERROR_TYPES), but the inline isinstance check overrides that.

Reproduction

import ssl
e = ssl.SSLCertVerificationError("certificate verify failed")
# is_local_validation_error logic:
isinstance(e, (ValueError, TypeError))  # True — it IS a ValueError via MRO
# So it gets flagged as non-retryable, even though classifier says retryable

Fix

Add ssl.SSLCertVerificationError (or its parent ssl.SSLError) to the exclusion list in is_local_validation_error, alongside the existing UnicodeError and json.JSONDecodeError exclusions from #14366.

Severity

Low. Cert errors rarely reach the API response handler — they are typically caught at the connection layer before the except Exception as api_error block. But if a provider returns a cert error mid-stream (e.g., TLS renegotiation failure after the HTTP request is sent), this would cause an unnecessary abort.

Pre-existing — not introduced by #14366. Discovered during red-team QA of that fix.

extent analysis

TL;DR

The is_local_validation_error check in run_agent.py should be updated to exclude ssl.SSLCertVerificationError to prevent incorrect classification as a non-retryable error.

Guidance

  • Review the is_local_validation_error function in run_agent.py to understand the current error classification logic.
  • Add ssl.SSLCertVerificationError or its parent ssl.SSLError to the exclusion list in is_local_validation_error to correctly classify cert verification errors as retryable.
  • Verify that the updated classification logic correctly handles ssl.SSLCertVerificationError instances by testing with a reproduction case similar to the one provided.
  • Consider reviewing other error types that may be incorrectly classified due to multiple inheritance, such as other ssl exceptions.

Example

def is_local_validation_error(api_error):
    # ... existing exclusions ...
    if isinstance(api_error, (UnicodeError, json.JSONDecodeError, ssl.SSLCertVerificationError)):
        return False
    # ... existing logic ...

Notes

This fix assumes that the is_local_validation_error function is the only place where ssl.SSLCertVerificationError is being incorrectly classified. Additional review of the codebase may be necessary to ensure that other error handling logic is correct.

Recommendation

Apply workaround: update the is_local_validation_error function to exclude ssl.SSLCertVerificationError to correctly classify cert verification errors as retryable, as this is a targeted fix for a specific issue.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

hermes - ✅(Solved) Fix ssl.SSLCertVerificationError misclassified as local validation error [3 pull requests, 1 participants]