Non-empty list/dict `parentUuid` raises uncaught `TypeError` in session chain builders, killing the whole read
メンテナーはふだん 2 日以内に返信
まだ誰も着手していません。
評価
調査の方向性
src/claude_agent_sdk/_internal/sessions.py の _build_conversation_chain(960〜964行付近)から始めてください。ここで parentUuid がセットに追加されています。その後、1507〜1508行付近の _build_subagent_chain を確認してください。issue の再現手順を一時的な CLAUDE_CONFIG_DIR に対して実行し、TypeError を確認します。文字列ではない parentUuid を持つトランスクリプトが残りのメッセージを返し、リストまたは辞書の値を扱う対照テストがあれば完了です。
索引モデルが issue の本文から書いたものです。
説明
Summary
The session chain builders assume parentUuid is a hashable string, but neither transcript parser validates parentUuid. A transcript entry with a non-empty list/dict parentUuid passes parsing, then raises an uncaught TypeError: unhashable type from get_session_messages (and the store-backed variants), killing the entire read instead of skipping or tolerating the malformed entry.
This is a correctness/error-handling bug, not a security vulnerability: triggering it requires a transcript file the caller already controls.
Version
- Repo:
anthropics/claude-agent-sdk-python - Package:
claude-agent-sdk0.2.181 - Commit:
22b8eb9c19adfa78759b79e22bd664a57843bb06(main, 2026-11-12)
Location
src/claude_agent_sdk/_internal/sessions.py:960-964 (_build_conversation_chain):
parent = entry.get("parentUuid")
if parent:
parent_uuids.add(parent)
set.add on a list/dict raises TypeError: unhashable type. The same unvalidated-parentUuid pattern appears at :1507-1508 in _build_subagent_chain (by_uuid.get(parent)). Neither _parse_transcript_entries (:897-926) nor _filter_transcript_entries (:1814-1829) checks parentUuid — they validate only type and that uuid is a str. get_session_messages has no try/except around the chain build (:1330-1338).
Precise trigger: the parentUuid must be a non-empty list/dict. Falsy []/{} are skipped by if parent: and do not raise (verified as a control case).
Minimal repro
Against a temporary CLAUDE_CONFIG_DIR (never the real ~/.claude), with a transcript whose second entry has parentUuid: ["x"]:
import json, os, tempfile
from pathlib import Path
from claude_agent_sdk._internal import sessions
session_id = "550e8400-e29b-41d4-a716-446655440001"
entries = [
{"uuid": "u1", "parentUuid": None, "type": "user",
"message": {"role": "user", "content": "first"}},
{"uuid": "u2", "parentUuid": ["x"], "type": "user",
"message": {"role": "user", "content": "second"}},
]
with tempfile.TemporaryDirectory() as tmp:
project_dir = Path(tmp) / "projects" / "tmp-proj"
project_dir.mkdir(parents=True)
(project_dir / f"{session_id}.jsonl").write_text(
"".join(json.dumps(e) + "\n" for e in entries), encoding="utf-8"
)
os.environ["CLAUDE_CONFIG_DIR"] = tmp
sessions.get_session_messages(session_id)
Observed: TypeError: unhashable type: 'list' propagates out of get_session_messages — the whole read fails, including the well-formed entries.
Expected: the malformed entry is skipped or its non-string parentUuid is treated as absent, and the read returns the remaining messages.
The store-backed variant (_filter_transcript_entries) and the subagent variant (_build_subagent_chain) share the unvalidated-parentUuid pattern by code reading; only the filesystem get_session_messages path was executed. A dict parentUuid (e.g. {"x": 1}) was not separately run — same unhashable mechanism as the list case.
Impact
One malformed entry in a session transcript makes the entire session unreadable via get_session_messages, instead of degrading gracefully. Any consumer reading sessions (resume flows, history views, tooling) hits an unhandled crash on the whole read. Local correctness impact only.
Suggested fix
Validate parentUuid in _parse_transcript_entries and _filter_transcript_entries (treat a non-string parentUuid as absent, or skip the entry), and/or guard the chain builders to ignore unhashable/non-string parent values.
Environment
- Python 3.12.3, Linux
- Verified end-to-end through the public
get_session_messages()against a temp config dir at the pinned commit above. Baseline: a string-parentUuidchain reads 2 messages; control: falsyparentUuid: []raises nothing.
- 主要言語
- Python
- スター
- 8.5k
- フォーク
- 1.4k
- 平均マージ
- 3日 10時間
- マージ済み PR(30日)
- 13
環境構築
このプロジェクトには開発コンテナ、Dockerfile、コントリビューションガイドがありません。まず README を読み、一般的な手順ははじめてのコントリビューションガイドを参照してください。
はじめの一歩
- issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
- 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
- リポジトリをフォークし、ブランチを切って変更します。
- issue 番号を参照したプルリクエストを送ります。
anthropics/claude-agent-sdk-python のほかの issue
-
bug
難易度 2/5 1〜3時間 初心者へのやさしさ 74/100
anthropics/claude-agent-sdk-python#1509 ·
メンテナーはふだん 2 日以内に返信
-
`parse_message` raises raw `TypeError` instead of `MessageParseError` on non-dict nested payloadsオープンbug good first issue
難易度 2/5 半日 初心者へのやさしさ 76/100
anthropics/claude-agent-sdk-python#1508 ·
メンテナーはふだん 2 日以内に返信
-
`fork_session` hangs forever on a cyclic `parentUuid` chain (no cycle guard in `_build_fork_lines`)オープンbug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
anthropics/claude-agent-sdk-python#1506 ·
メンテナーはふだん 2 日以内に返信
-
ClaudeSDKClient.connect() with an async iterable closes stdin, so follow-up query() fails対応中かも @m4xkushnir が 19 日前に担当しました。 オープンbug
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
anthropics/claude-agent-sdk-python#1443 ·
メンテナーはふだん 2 日以内に返信
-
fork_session drops transcript entries containing U+2028/U+2029/U+0085 (str.splitlines), breaking the parentUuid chain対応中かも @mangeshraut712 が 19 日前に担当しました。 オープンbug good first issue
難易度 2/5 1〜3時間 初心者へのやさしさ 78/100
anthropics/claude-agent-sdk-python#1441 ·
メンテナーはふだん 2 日以内に返信
anthropics/claude-agent-sdk-python の issue をすべて見る
似ている issue
-
難易度 2/5 1〜3時間 初心者へのやさしさ 72/100
dbt-labs/spark-utils#51 ·
-
bug pydanty:is-working
難易度 2/5 1〜3時間 初心者へのやさしさ 68/100
pydantic/pydantic-ai#13444 ·
メンテナーはふだん 1 日以内に返信
-
good first issue help wanted
難易度 2/5 1〜3時間 初心者へのやさしさ 82/100
-
good first issue help wanted
難易度 1/5 1時間未満 初心者へのやさしさ 72/100
-
changelog investigate
難易度 1/5 1時間未満 初心者へのやさしさ 68/100
ramnes/notion-sdk-py#502 ·