Skip to content

[Bug]: /journey crashes when a skill’s frontmatter metadata is not a dict #57986

Description

@jonharris0n

Bug Description

I hit a reproducible crash in /journey and tracked it down to the learning graph builder.

Symptom
Running /journey failed with:

Code
· text
'NoneType' object has no attribute 'get'
In my local repro, the traceback landed here:

Code
· text
hermes_cli/journey.py -> agent/learning_graph.py -> _category()
More specifically, this line pattern was the problem:

Code
· python
fm.get("metadata", {}).get("hermes", {})
Root cause
/journey assumes parsed skill frontmatter always gives metadata.hermes as a dict.

In practice, some real SKILL.md files can parse into looser shapes, for example:

Code
· yaml
metadata:
or

Code
· yaml
metadata: oops
That means metadata may be None or a scalar instead of a mapping, and then the code calls .get() on something that is not a dict.

So this is not just “bad user input” in the abstract — it can happen with real skill files that the system is willing to read.

Expected behavior
/journey should degrade gracefully:

if metadata is missing, null, or malformed, treat it as empty
keep rendering the journey graph
fall back to other sources where possible (e.g. folder-derived category)
Actual behavior
A malformed or loosely parsed metadata field can crash /journey entirely.

Minimal fix direction
Normalize metadata.hermes before reading it:

if metadata is not a dict, use {}
if metadata.hermes is not a dict, use {}
then read category / related_skills from that safe mapping
That was enough in my local patch to stop the crash without thinning the overall journey data model. It just turns “fatal parse-shape mismatch” into “missing optional metadata”.

Verification
After applying that defensive guard locally:

/journey rendered successfully
targeted regression tests for
metadata:
metadata: oops passed
Why I think this is worth fixing
user-facing built-in command crash
small, low-risk robustness fix
behavior is consistent with other defensive metadata handling already present elsewhere in the codebase
If useful, I can also post the minimal patch shape, but I figured the bug report + root cause was the useful part first.

If you want, I can also compress that into a shorter, more forum-native version with less engineering detail.

Steps to Reproduce

  1. Run /journey from TUI

Expected Behavior

Journey graph output appears.

Actual Behavior

Received: "'NoneType' object has no attribute 'get'"

Affected Component

CLI (interactive chat)

Messaging Platform (if gateway-related)

No response

Debug Report

Report       https://paste.rs/3yunm
agent.log    https://paste.rs/OSp9U
gateway.log  https://paste.rs/hlvVY
gui.log      https://paste.rs/z0TxP

Operating System

Mac OS 26.5.1

Python Version

3.14.6

Hermes Version

0.18.0

Additional Logs / Traceback (optional)

Root Cause Analysis (optional)

No response

Proposed Fix (optional)

No response

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    P3Low — cosmetic, nice to havebugcomp/agentCore agent runtime: loop, agent_init, prompt builder, context-compression, responses endpointduplicateThis issue or pull request already existstool/memoryMemory tool and memory providerstool/skillsSkills system (list, view, manage)type/bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions