Skip to content

fix(deps): bump pydantic to 2.13.4 to avoid pydantic-core thread segfault#29021

Merged
austinpickett merged 2 commits into
NousResearch:mainfrom
fabiosiqueira:fix/pydantic-core-thread-segfault
May 20, 2026
Merged

fix(deps): bump pydantic to 2.13.4 to avoid pydantic-core thread segfault#29021
austinpickett merged 2 commits into
NousResearch:mainfrom
fabiosiqueira:fix/pydantic-core-thread-segfault

Conversation

@fabiosiqueira

Copy link
Copy Markdown
Contributor

Summary

Bumps pydantic from 2.12.52.13.4 (pulling in pydantic-core 2.41.52.46.4) to fix a hard SIGSEGV that crashes every codex_responses dispatch path (xai-oauth, openai-codex).

pydantic-core==2.41.5 segfaults when the OpenAI SDK's Responses API resource (client.responses.create(...) / client.responses.stream(...)) is exercised from a non-main threading.Thread. Hermes always wraps codex calls in threading.Thread(target=_call, daemon=True) at agent/chat_completion_helpers.py:159, so the crash is 100% reproducible whenever the active provider uses api_mode=codex_responses.

The crash is silent to end users because hermes_cli/oneshot.py:174-188 redirects both stdout and stderr to /dev/null for the entire call tree. Operator symptom: hermes -z "ping" exits with no output; under timeout the harness reports dumped core / exit 139.

Minimal repro (no Hermes, just the venv)

import threading
from openai import OpenAI
cli = OpenAI(api_key="sk-bogus", base_url="https://api.openai.com/v1")
def go():
    try: cli.responses.create(model="gpt-4o", input="ping")
    except BaseException as e: print(type(e).__name__)
threading.Thread(target=go).start()
# → SIGSEGV with pydantic-core 2.41.5
# → clean AuthenticationError(401) with 2.46.4

The same script using cli.chat.completions.create(stream=True) from a thread works — bug is specific to the Responses resource × pydantic-core 2.41.5 × non-main thread.

Bisection

pydantic / pydantic-core thread + responses.create Result
2.12.5 / 2.41.5 yes SIGSEGV
2.13.4 / 2.46.4 yes 401 (ok)
2.12.5 / 2.41.5 no (main thread) 401 (ok)
2.12.5 / 2.41.5 yes, chat.completions instead 401 (ok)

Diff between a fresh-venv (no crash) and the Hermes venv (crash) was isolated to pydantic-core aloneanyio, jiter, certifi, idna, httpx, etc. were ruled out individually.

Test plan

  • Minimal repro above runs to completion with 2.13.4/2.46.4
  • hermes -z "ping" against xai-oauth / grok-4.3 no longer SIGSEGVs (validated end-to-end in the Hermes venv on Linux x86_64 musl)
  • _run_agent("ping", model="grok-4.3", provider="xai-oauth") returns 'pong' instead of crashing
  • pip install --dry-run pydantic==2.13.4 in the Hermes venv touches only pydantic + pydantic-core; all other pinned deps already satisfy 2.13.4's constraints (annotated-types>=0.6.0, typing-extensions>=4.14.1, typing-inspection>=0.4.2)

Platforms tested

  • Linux 6.8.0 x86_64, musllinux (Alpine container), Python 3.11.15

Related diagnosability concern (not fixed here)

Worth a follow-up: hermes_cli/oneshot.py:174-188 swallows stderr unconditionally, which is what made this a multi-hour investigation instead of a 30-second triage. Even with PYTHONFAULTHANDLER=1, the C-level stack never reaches the operator. Two cheap improvements would dramatically improve future SIGSEGV diagnosability:

  1. Redirect stderr to a temp file and tail it to the real stderr on non-zero exit (instead of /dev/null).
  2. faulthandler.enable(file=open(<known path>, "w"), all_threads=True) before the redirect block.

Happy to send these as a separate PR if you'd like.

🤖 Generated with Claude Code

…ault

pydantic-core 2.41.5 (pulled by pydantic==2.12.5) segfaults when the
OpenAI SDK's Responses API resource (client.responses.create /
client.responses.stream) is exercised from a non-main threading.Thread.

Hermes always dispatches codex_responses calls from a daemon thread in
agent/chat_completion_helpers.py:_call, so the crash is 100%
reproducible whenever the active provider is xai-oauth or openai-codex.
Symptom: `hermes -z "ping"` (or any oneshot path) dies with SIGSEGV /
exit 139 and zero output — hermes_cli/oneshot.py redirects stderr to
/dev/null, hiding the crash.

Bumping pydantic to 2.13.4 pulls in pydantic-core 2.46.4, which
eliminates the crash. Verified end-to-end: `hermes -z "ping"` against
xai-oauth/grok-4.3 now returns the expected response.

Minimal repro (any OpenAI base_url; not xAI-specific):

    import threading
    from openai import OpenAI
    cli = OpenAI(api_key="sk-bogus", base_url="https://api.openai.com/v1")
    def go():
        try: cli.responses.create(model="gpt-4o", input="ping")
        except BaseException as e: print(type(e).__name__)
    threading.Thread(target=go).start()
    # → SIGSEGV with pydantic-core 2.41.5; clean 401 with 2.46.4
@fabiosiqueira fabiosiqueira requested a review from a team May 20, 2026 01:27
@alt-glitch alt-glitch added type/bug Something isn't working dependencies Pull requests that update a dependency file comp/agent Core agent loop, run_agent.py, prompt builder P1 High — major feature broken, no workaround labels May 20, 2026

@austinpickett austinpickett left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review — fix(deps): bump pydantic to 2.13.4 to avoid pydantic-core thread segfault

2 actual files changed (pyproject.toml + uv.lock). 47 of 49 files in the diff are merge noise from main.


Assessment

  • pydantic: 2.12.5 → 2.13.4 (minor version bump)
  • pydantic-core (transitive): 2.41.5 → 2.46.4 (5 minor versions forward with thread-safety fixes)
  • Consistent with project's strict ==X.Y.Z exact-pin convention
  • All transitive consumers (openai, mcp, honcho-ai, pydantic-settings) use >= lower bounds satisfied by 2.13.4
  • Commit message is exemplary — includes minimal repro, identifies exact call site (chat_completion_helpers.py:_call from daemon thread), confirms end-to-end verification

Breaking change risk: Low

Pydantic follows semver. Minor bump, lockfile resolved cleanly with no conflicts.

Suggestion (non-blocking)

Consider adding a CI smoke test that exercises model validation from a non-main thread to prevent this class of segfault from regressing if pydantic-core is ever downgraded.

Verdict: LGTM — clean, focused, well-documented fix for a real crash.

Reviewed by Hermes Agent

@austinpickett austinpickett merged commit 57a6105 into NousResearch:main May 20, 2026
17 of 18 checks passed
dannyJ848 pushed a commit to dannyJ848/hermes-agent that referenced this pull request May 21, 2026
…ault (NousResearch#29021)

* fix(deps): bump pydantic to 2.13.4 to avoid pydantic-core thread segfault

pydantic-core 2.41.5 (pulled by pydantic==2.12.5) segfaults when the
OpenAI SDK's Responses API resource (client.responses.create /
client.responses.stream) is exercised from a non-main threading.Thread.

Hermes always dispatches codex_responses calls from a daemon thread in
agent/chat_completion_helpers.py:_call, so the crash is 100%
reproducible whenever the active provider is xai-oauth or openai-codex.
Symptom: `hermes -z "ping"` (or any oneshot path) dies with SIGSEGV /
exit 139 and zero output — hermes_cli/oneshot.py redirects stderr to
/dev/null, hiding the crash.

Bumping pydantic to 2.13.4 pulls in pydantic-core 2.46.4, which
eliminates the crash. Verified end-to-end: `hermes -z "ping"` against
xai-oauth/grok-4.3 now returns the expected response.

Minimal repro (any OpenAI base_url; not xAI-specific):

    import threading
    from openai import OpenAI
    cli = OpenAI(api_key="sk-bogus", base_url="https://api.openai.com/v1")
    def go():
        try: cli.responses.create(model="gpt-4o", input="ping")
        except BaseException as e: print(type(e).__name__)
    threading.Thread(target=go).start()
    # → SIGSEGV with pydantic-core 2.41.5; clean 401 with 2.46.4

* chore(deps): regenerate uv.lock for pydantic 2.13.4 bump
Lillard01 pushed a commit to Lillard01/hermes-agent that referenced this pull request May 21, 2026
…ault (NousResearch#29021)

* fix(deps): bump pydantic to 2.13.4 to avoid pydantic-core thread segfault

pydantic-core 2.41.5 (pulled by pydantic==2.12.5) segfaults when the
OpenAI SDK's Responses API resource (client.responses.create /
client.responses.stream) is exercised from a non-main threading.Thread.

Hermes always dispatches codex_responses calls from a daemon thread in
agent/chat_completion_helpers.py:_call, so the crash is 100%
reproducible whenever the active provider is xai-oauth or openai-codex.
Symptom: `hermes -z "ping"` (or any oneshot path) dies with SIGSEGV /
exit 139 and zero output — hermes_cli/oneshot.py redirects stderr to
/dev/null, hiding the crash.

Bumping pydantic to 2.13.4 pulls in pydantic-core 2.46.4, which
eliminates the crash. Verified end-to-end: `hermes -z "ping"` against
xai-oauth/grok-4.3 now returns the expected response.

Minimal repro (any OpenAI base_url; not xAI-specific):

    import threading
    from openai import OpenAI
    cli = OpenAI(api_key="sk-bogus", base_url="https://api.openai.com/v1")
    def go():
        try: cli.responses.create(model="gpt-4o", input="ping")
        except BaseException as e: print(type(e).__name__)
    threading.Thread(target=go).start()
    # → SIGSEGV with pydantic-core 2.41.5; clean 401 with 2.46.4

* chore(deps): regenerate uv.lock for pydantic 2.13.4 bump
Gpapas pushed a commit to Gpapas/hermes-agent that referenced this pull request May 23, 2026
…ault (NousResearch#29021)

* fix(deps): bump pydantic to 2.13.4 to avoid pydantic-core thread segfault

pydantic-core 2.41.5 (pulled by pydantic==2.12.5) segfaults when the
OpenAI SDK's Responses API resource (client.responses.create /
client.responses.stream) is exercised from a non-main threading.Thread.

Hermes always dispatches codex_responses calls from a daemon thread in
agent/chat_completion_helpers.py:_call, so the crash is 100%
reproducible whenever the active provider is xai-oauth or openai-codex.
Symptom: `hermes -z "ping"` (or any oneshot path) dies with SIGSEGV /
exit 139 and zero output — hermes_cli/oneshot.py redirects stderr to
/dev/null, hiding the crash.

Bumping pydantic to 2.13.4 pulls in pydantic-core 2.46.4, which
eliminates the crash. Verified end-to-end: `hermes -z "ping"` against
xai-oauth/grok-4.3 now returns the expected response.

Minimal repro (any OpenAI base_url; not xAI-specific):

    import threading
    from openai import OpenAI
    cli = OpenAI(api_key="sk-bogus", base_url="https://api.openai.com/v1")
    def go():
        try: cli.responses.create(model="gpt-4o", input="ping")
        except BaseException as e: print(type(e).__name__)
    threading.Thread(target=go).start()
    # → SIGSEGV with pydantic-core 2.41.5; clean 401 with 2.46.4

* chore(deps): regenerate uv.lock for pydantic 2.13.4 bump
Mucky010 pushed a commit to Mucky010/hermes-agent that referenced this pull request May 24, 2026
…ault (NousResearch#29021)

* fix(deps): bump pydantic to 2.13.4 to avoid pydantic-core thread segfault

pydantic-core 2.41.5 (pulled by pydantic==2.12.5) segfaults when the
OpenAI SDK's Responses API resource (client.responses.create /
client.responses.stream) is exercised from a non-main threading.Thread.

Hermes always dispatches codex_responses calls from a daemon thread in
agent/chat_completion_helpers.py:_call, so the crash is 100%
reproducible whenever the active provider is xai-oauth or openai-codex.
Symptom: `hermes -z "ping"` (or any oneshot path) dies with SIGSEGV /
exit 139 and zero output — hermes_cli/oneshot.py redirects stderr to
/dev/null, hiding the crash.

Bumping pydantic to 2.13.4 pulls in pydantic-core 2.46.4, which
eliminates the crash. Verified end-to-end: `hermes -z "ping"` against
xai-oauth/grok-4.3 now returns the expected response.

Minimal repro (any OpenAI base_url; not xAI-specific):

    import threading
    from openai import OpenAI
    cli = OpenAI(api_key="sk-bogus", base_url="https://api.openai.com/v1")
    def go():
        try: cli.responses.create(model="gpt-4o", input="ping")
        except BaseException as e: print(type(e).__name__)
    threading.Thread(target=go).start()
    # → SIGSEGV with pydantic-core 2.41.5; clean 401 with 2.46.4

* chore(deps): regenerate uv.lock for pydantic 2.13.4 bump
Bryce-huang pushed a commit to wbkunlun/hermes-agent that referenced this pull request May 29, 2026
…ault (NousResearch#29021)

* fix(deps): bump pydantic to 2.13.4 to avoid pydantic-core thread segfault

pydantic-core 2.41.5 (pulled by pydantic==2.12.5) segfaults when the
OpenAI SDK's Responses API resource (client.responses.create /
client.responses.stream) is exercised from a non-main threading.Thread.

Hermes always dispatches codex_responses calls from a daemon thread in
agent/chat_completion_helpers.py:_call, so the crash is 100%
reproducible whenever the active provider is xai-oauth or openai-codex.
Symptom: `hermes -z "ping"` (or any oneshot path) dies with SIGSEGV /
exit 139 and zero output — hermes_cli/oneshot.py redirects stderr to
/dev/null, hiding the crash.

Bumping pydantic to 2.13.4 pulls in pydantic-core 2.46.4, which
eliminates the crash. Verified end-to-end: `hermes -z "ping"` against
xai-oauth/grok-4.3 now returns the expected response.

Minimal repro (any OpenAI base_url; not xAI-specific):

    import threading
    from openai import OpenAI
    cli = OpenAI(api_key="sk-bogus", base_url="https://api.openai.com/v1")
    def go():
        try: cli.responses.create(model="gpt-4o", input="ping")
        except BaseException as e: print(type(e).__name__)
    threading.Thread(target=go).start()
    # → SIGSEGV with pydantic-core 2.41.5; clean 401 with 2.46.4

* chore(deps): regenerate uv.lock for pydantic 2.13.4 bump
#AI commit#
gweeteve pushed a commit to gweeteve/hermes-agent that referenced this pull request Jun 2, 2026
…ault (NousResearch#29021)

* fix(deps): bump pydantic to 2.13.4 to avoid pydantic-core thread segfault

pydantic-core 2.41.5 (pulled by pydantic==2.12.5) segfaults when the
OpenAI SDK's Responses API resource (client.responses.create /
client.responses.stream) is exercised from a non-main threading.Thread.

Hermes always dispatches codex_responses calls from a daemon thread in
agent/chat_completion_helpers.py:_call, so the crash is 100%
reproducible whenever the active provider is xai-oauth or openai-codex.
Symptom: `hermes -z "ping"` (or any oneshot path) dies with SIGSEGV /
exit 139 and zero output — hermes_cli/oneshot.py redirects stderr to
/dev/null, hiding the crash.

Bumping pydantic to 2.13.4 pulls in pydantic-core 2.46.4, which
eliminates the crash. Verified end-to-end: `hermes -z "ping"` against
xai-oauth/grok-4.3 now returns the expected response.

Minimal repro (any OpenAI base_url; not xAI-specific):

    import threading
    from openai import OpenAI
    cli = OpenAI(api_key="sk-bogus", base_url="https://api.openai.com/v1")
    def go():
        try: cli.responses.create(model="gpt-4o", input="ping")
        except BaseException as e: print(type(e).__name__)
    threading.Thread(target=go).start()
    # → SIGSEGV with pydantic-core 2.41.5; clean 401 with 2.46.4

* chore(deps): regenerate uv.lock for pydantic 2.13.4 bump
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/agent Core agent loop, run_agent.py, prompt builder dependencies Pull requests that update a dependency file P1 High — major feature broken, no workaround type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants