hermes - ✅(Solved) Fix quick_commands with non-dict values crashes slash command dispatch [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#18816Fetched 2026-05-03 04:54:08
View on GitHub
Comments
0
Participants
1
Timeline
7
Reactions
0
Participants
Timeline (top)
cross-referenced ×3labeled ×3referenced ×1

Error Message

Error: 'str' object has no attribute 'get'

Root Cause

All slash commands that match a quick_commands key crash — even if the key overlaps with a valid skill command, because quick_commands is checked BEFORE skill commands in the dispatch chain. For example, if both quick_commands.mul-agents (string) and a skill command /mul-agents exist, the broken quick_commands entry poisons /mul-agents and prevents the skill from loading.

Fix Action

Fix

Guard with isinstance(qcmd, dict) before accessing dict methods:

if not isinstance(qcmd, dict):
    logger.warning(f"quick_commands entry for {base_cmd} is not a dict, skipping")
    # fall through to plugin commands / skill commands checks
elif qcmd.get("type") == "exec":
    ...

PR fix notes

PR #18817: fix(cli): guard quick_commands against non-dict values

Description (problem / solution / changelog)

Fix: Guard quick_commands against non-dict values

Problem

When quick_commands values in ~/.hermes/config.yaml are not dicts (e.g., strings like foo: ''), the slash command dispatch at cli.py:6583 crashes with:

Error: 'str' object has no attribute 'get'

This blocks all matching slash commands — even valid skill commands — because quick_commands is checked before the skill dispatch chain.

Reproduction

# ~/.hermes/config.yaml
quick_commands:
  foo: ''

Then type /foo — crash.

Fix

Add isinstance(qcmd, dict) guard before accessing .get(). Non-dict entries now get a warning log and fall through to plugin/skill command checks instead of crashing.

Fixes #18816

Changed files

  • cli.py (modified, +5/-1)

PR #18850: fix(cli): guard quick_commands against non-dict values

Description (problem / solution / changelog)

Fix: Guard quick_commands against non-dict values

Problem

cli.py:6584 calls qcmd.get("type") on whatever value is in quick_commands — no validation that it's actually a dict. If a user has a string, int, or null value in their quick_commands config, all slash commands matching that key crash with AttributeError: 'str' object has no attribute 'get'.

Even worse, a broken quick_commands entry poisons any overlapping skill command, because quick_commands is checked BEFORE skill commands in the dispatch chain.

Reproduction

# ~/.hermes/config.yaml
quick_commands:
  foo: ''  # string instead of dict

Then /fooError: 'str' object has no attribute 'get'

Fix

Added isinstance(qcmd, dict) guard before accessing dict methods, matching the pattern already used in gateway/run.py:5214-5215. If the value is not a dict, we log a warning and fall through to plugin/skill command dispatch instead of crashing.

Testing

  • Verified the fix applies cleanly on top of current origin/main
  • The gateway already has this guard (lines 5214-5215), so this brings CLI parity with gateway

Fixes #18816

Changed files

  • cli.py (modified, +3/-1)

PR #18937: fix(skills): exclude hidden dirs from skill search, guard cyclic symlinks, handle non-dict quick_commands

Description (problem / solution / changelog)

Fixes #18900, #18809, #18816

#18900 -- _find_skill rglob leaks into .archive, .git, .github, .hub Replace bare rglob in _find_skill with iter_skill_index_files which already excludes those dirs.

#18809 -- os.walk(followlinks=True) infinite-loop on cyclic symlinks Add seen-inode tracking to iter_skill_index_files. If a directory inode pair has already been visited the subtree is pruned. Non-cyclic symlinks are still followed.

#18816 -- quick_commands with non-dict values crashes slash command dispatch Add isinstance(qcmd, dict) guard in both gateway/run.py and cli.py before calling .get(). Misconfigured entries return a clear error message instead of crashing with AttributeError.

14 new tests in tests/test_skill_rglob_and_quick_commands.py, all passing.

Changed files

  • agent/skill_utils.py (modified, +17/-0)
  • cli.py (modified, +6/-0)
  • gateway/run.py (modified, +5/-0)
  • tests/test_skill_rglob_and_quick_commands.py (added, +139/-0)
  • tools/skill_manager_tool.py (modified, +7/-2)

Code Example

quick_commands:
     foo: ''

---

Error: 'str' object has no attribute 'get'

---

base_cmd = cmd_lower.split()[0]
quick_commands = self.config.get("quick_commands", {})
if base_cmd.lstrip("/") in quick_commands:
    qcmd = quick_commands[base_cmd.lstrip("/")]
    if qcmd.get("type") == "exec":          # <-- crash: str has no .get()

---

if not isinstance(qcmd, dict):
    logger.warning(f"quick_commands entry for {base_cmd} is not a dict, skipping")
    # fall through to plugin commands / skill commands checks
elif qcmd.get("type") == "exec":
    ...
RAW_BUFFERClick to expand / collapse

Bug

cli.py:6577 calls qcmd.get("type") on whatever value is in quick_commands — no validation that it is actually a dict.

Reproduction

  1. Add this to ~/.hermes/config.yaml:
    quick_commands:
      foo: ''
  2. Start Hermes CLI
  3. Type /foo

Result

Error: 'str' object has no attribute 'get'

All slash commands that match a quick_commands key crash — even if the key overlaps with a valid skill command, because quick_commands is checked BEFORE skill commands in the dispatch chain. For example, if both quick_commands.mul-agents (string) and a skill command /mul-agents exist, the broken quick_commands entry poisons /mul-agents and prevents the skill from loading.

Location

cli.py:6573-6577:

base_cmd = cmd_lower.split()[0]
quick_commands = self.config.get("quick_commands", {})
if base_cmd.lstrip("/") in quick_commands:
    qcmd = quick_commands[base_cmd.lstrip("/")]
    if qcmd.get("type") == "exec":          # <-- crash: str has no .get()

Fix

Guard with isinstance(qcmd, dict) before accessing dict methods:

if not isinstance(qcmd, dict):
    logger.warning(f"quick_commands entry for {base_cmd} is not a dict, skipping")
    # fall through to plugin commands / skill commands checks
elif qcmd.get("type") == "exec":
    ...

extent analysis

TL;DR

Add a type check for qcmd to ensure it's a dictionary before calling get("type") to prevent the 'str' object has no attribute 'get' error.

Guidance

  • Verify that all values in the quick_commands configuration are dictionaries to prevent this issue.
  • Check the ~/.hermes/config.yaml file for any non-dictionary values under the quick_commands key and update them to be dictionaries.
  • Consider adding input validation to the configuration parsing code to prevent non-dictionary values from being accepted.
  • If a non-dictionary value is found, log a warning and skip the quick command to prevent the error and allow the skill command to be checked.

Example

if not isinstance(qcmd, dict):
    logger.warning(f"quick_commands entry for {base_cmd} is not a dict, skipping")
    # fall through to plugin commands / skill commands checks
elif qcmd.get("type") == "exec":
    # existing code

Notes

This fix assumes that the quick_commands configuration should only contain dictionary values. If non-dictionary values are intended to be supported, additional handling will be needed.

Recommendation

Apply the suggested workaround by adding the type check for qcmd to prevent the error and ensure that the code can handle non-dictionary values in the quick_commands configuration.

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 quick_commands with non-dict values crashes slash command dispatch [3 pull requests, 1 participants]