Skip to content

fix(cli): TypeError concatenating queued note onto multimodal (image) message#37173

Merged
teknium1 merged 3 commits into
mainfrom
hermes/hermes-17e880d9
Jun 2, 2026
Merged

fix(cli): TypeError concatenating queued note onto multimodal (image) message#37173
teknium1 merged 3 commits into
mainfrom
hermes/hermes-17e880d9

Conversation

@teknium1

@teknium1 teknium1 commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

Summary

The interactive CLI no longer crashes when a queued /model or /reload-skills note is prepended to a message that has an attached image.

Root cause: the two prepend sites did note + "\n\n" + agent_message, but agent_message becomes a list of OpenAI content parts (text + image_url) when an image is attached to a vision-capable model — raising TypeError: can only concatenate str (not "list") to str in the agent thread.

Changes

  • cli.py: new _prepend_note_to_message(message, note) helper — string → prepend; multimodal list → fold note into first text part (or insert a leading text block when image-only); unknown shapes returned unchanged (fail-open). Both prepend sites now route through it.
  • tests/cli/test_prepend_note_to_message.py: 9 tests covering string, empty note, image-only, text+image, empty-text-part, no-mutation, and the exact repro shape.

Validation

Before After
/model … + pasted image same turn TypeError crash in agent thread note folded in, image preserved
plain-string message works works (unchanged)

Targeted tests: 9/9 pass. E2E confirmed the old line raises the exact reported TypeError and the helper handles the image-only repro without mutating the original message. The _voice_prefix concat site is already isinstance(message, str)-guarded, so these were the only two vulnerable sites.

Salvage of #37081 by @xxxigm (cherry-picked, authorship preserved). Also fixes the same crash reported in #37080 by @helix4u, who closed his own PR in favor of this one's fuller test coverage — both contributors credited.

Infographic

retro-pop-grid

xxxigm added 3 commits June 1, 2026 20:14
Sending an image to a vision model turns the user message into a list of
OpenAI-style content parts. When a /model or /reload-skills note was queued
for the same turn, the CLI did `note + "\n\n" + agent_message`, crashing the
agent thread with:

    TypeError: can only concatenate str (not "list") to str

Repro: `/model gpt-5.5 --provider openai-codex`, then paste+send an image.

Add _prepend_note_to_message(), which folds the note into the first text
part of a content-parts list (or inserts a leading text part for image-only
messages) and keeps the plain-string path unchanged. Used for both the
model-switch and skills-reload notes.
Regression coverage for the multimodal-message TypeError: note folding into
text parts, image-only insertion, empty-note passthrough, and unknown-shape
fail-open.
Adopt the cleaner handling from PR #37080: coerce/strip the note and
skip the extra newlines when the underlying message (or text part) is
empty, while keeping the safer fail-open behavior for unknown shapes.
@github-actions

github-actions Bot commented Jun 2, 2026

Copy link
Copy Markdown
Contributor

🔎 Lint report: hermes/hermes-17e880d9 vs origin/main

ruff

Total: 0 on HEAD, 0 on base (➖ 0)

🆕 New issues: none

✅ Fixed issues: none

Unchanged: 0 pre-existing issues carried over.

ty (type checker)

Total: 9620 on HEAD, 9619 on base (🆕 +1)

🆕 New issues (1):

Rule Count
invalid-argument-type 1
First entries
cli.py:2143: [invalid-argument-type] invalid-argument-type: Argument to bound method `dict.get` is incorrect: Expected `Never`, found `Literal["type"]`

✅ Fixed issues: none

Unchanged: 4984 pre-existing issues carried over.

Diagnostics are surfaced as warnings — this check never fails the build.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants