Skills bundle hash crashes on bytes content
NousResearch/hermes-agent · cluster 2739 · hermes cli
Data as of
Nothing open on GitHub. Fix merged in #19575. Check it covers your case.
The short answer
- Known?
- Yes. 17 related items grouped here, 4 issues already closed.
- Fix event
- A fix was merged to main in PR #19575. Check it covers your case. No release data is tracked.
- Tracker
- The maintainers' tracker marks this
partially resolved, deciding PR #19575. That is separate from the fix event. - Still open
- Nothing open on GitHub.
A bug where bundle_content_hash raises an AttributeError when encountering bytes values during skills check/update operations. Multiple fix attempts address handling bytes alongside string content in the hashing logic.
Open issues0
Open PRs0
Fixes on record
-
#19575 fix(skills): hash byte-backed bundle files (closes #13408)
files:
scripts/release.py,tests/tools/test_skills_hub.py,tools/skills_hub.pyShow the diff
-
scripts/release.py@@ -633,6 +633,8 @@ "[redacted:email]": "CIRWEL", "[redacted:email]": "molvikar", "[redacted:email]": "nftpoetrist", + "[redacted:email]": "colorcross", + "[redacted:email]": "zhao0112", "[redacted:email]": "leozeli", "[redacted:email]": "LehaoLin", "[redacted:email]": "I3eg1nner", -
tests/tools/test_skills_hub.py@@ -901,6 +901,69 @@ def test_bundle_content_hash_matches_installed_content_hash(self, tmp_path): assert bundle_content_hash(bundle) == content_hash(skill_dir) + def test_bundle_content_hash_accepts_binary_files(self): + bundle = SkillBundle( + name="demo-binary-skill", + files={ + "SKILL.md": "# Demo\n", + "assets/logo.png": b"\x89PNG\r\n\x1a\nbinary", + }, + source="github", + identifier="owner/repo/demo-binary-skill", + trust_level="community", + ) + + digest = bundle_content_hash(bundle) + + assert digest.startswith("sha256:") + + def test_bundle_content_hash_bytes_matches_str_equivalent(self): + """Bytes content must hash identically to its str-decoded form.""" + text_bundle = SkillBundle( + name="demo-skill", + files={ + "SKILL.md": "same content", + "references/checklist.md": "- [ ] security\n", + }, + source="github", + identifier="owner/repo/demo-skill", + trust_level="community", + ) + bytes_bundle = SkillBundle( + name="demo-skill", + files={ + "SKILL.md": b"same content", + "references/checklist.md": b"- [ ] security\n", + }, + source="github", + identifier="owner/repo/demo-skill", + trust_level="community", + ) + + assert bundle_content_hash(bytes_bundle) == bundle_content_hash(text_bundle) + + def test_bundle_content_hash_mixed_matches_on_disk(self, tmp_path): + """In-memory bundle hash must equal on-disk content_hash for mixed bytes+str.""" + from tools.skills_guard import content_hash + + bundle = SkillBundle( + name="demo-skill", + files={ + "SKILL.md": b"# Demo Skill\n", + "references/checklist.md": "- [ ] security\n", + }, + source="github", + identifier="owner/repo/demo-skill", + trust_level="community", + ) + skill_dir = tmp_path / "demo-skill" + skill_dir.mkdir() + (skill_dir / "SKILL.md").write_bytes(b"# Demo Skill\n") + (skill_dir / "references").mkdir() + (skill_dir / "references" / "checklist.md").write_text("- [ ] security\n") + + assert bundle_content_hash(bundle) == content_hash(skill_dir) + def test_reports_update_when_remote_hash_differs(self): lock = MagicMock() lock.list_installed.return_value = [{ -
tools/skills_hub.py@@ -2801,7 +2801,11 @@ def bundle_content_hash(bundle: SkillBundle) -> str: """Compute a deterministic hash for an in-memory skill bundle.""" h = hashlib.sha256() for rel_path in sorted(bundle.files): - h.update(bundle.files[rel_path].encode("utf-8")) + content = bundle.files[rel_path] + if isinstance(content, bytes): + h.update(content) + else: + h.update(content.encode("utf-8")) return f"sha256:{h.hexdigest()[:16]}"
-
12 PRs closed without merging
From the close comments: done elsewhere 6 · duplicate 4 · merged via another change 1 · other 1
-
#2740 fix(skills): handle bytes content in bundle_content_hash · done elsewhere →
3072e55,91ea3ae,#9925 -
#3751 Handle byte-backed skill bundle hashes · done elsewhere →
3072e55 -
#12518 fix(skills_hub): handle bytes content in bundle_content_hash · duplicate →
#2740 -
#13424 fix(skills_hub): handle bytes content in bundle_content_hash · duplicate →
#2740 -
#13531 fix(skills): handle bytes in bundle content hash · other →
#3751
Show 7 more
-
#14108 fix(skills): hash byte-backed bundle files · duplicate →
#13531 -
#19079 fix: handle bytes values in bundle_content_hash() · done elsewhere →
#19575,#19328 -
#19081 fix(skills): handle bytes values in bundle_content_hash · done elsewhere →
#19575,#19328 -
#19116 fix(skills): hash bytes bundle contents · duplicate →
#9925,#14108,#13531,#13408 -
#19120 fix(skills): handle bytes values in bundle_content_hash — fixes AttributeError on skills check/update (#19090) · done elsewhere →
#19575,#19328 -
#19145 fix(skills): handle bytes in bundle update hash · done elsewhere →
#19575,#19328 -
#19328 fix(skills): hash byte-backed bundle files (closes #13408) · merged via another change →
#19575
Closed issues · 4
How this cluster was grouped
-
Link evidence (
partly structural links): some members are connected by structural evidence (shared changed files, or a closing/superseded reference); the rest are joined by an automated relevance judgement over their text. - Members outside that structural core may belong to a different underlying problem.
-
Pairwise link density
0.14: the share of item pairs that carry a link, counting a structural link in full and a relevance-only link at 0.36.1.00means every pair is linked.
Pick up a Lab task
Check whether a fix covers the open issues here, with your own agent. Bring back evidence for maintainers.
Open the LabAt a glance
- Subsystem
- hermes cli
- Merged PRs
- #19575
- Closed issues
- 4
- Attempts
- 12 PRs closed without merging
- Fix link checked
- 4 May 2026