hermes - ✅(Solved) Fix [Bug]: UnicodeDecodeError and AttributeError in Windows gateway process scanning [10 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#17049Fetched 2026-04-29 06:37:36
View on GitHub
Comments
0
Participants
1
Timeline
16
Reactions
0
Author
Participants
Timeline (top)
cross-referenced ×10labeled ×3referenced ×3

Running hermes setup on Windows fails with two related errors:

  1. UnicodeDecodeError in the subprocess reader thread due to non-UTF-8 encoded wmic output
  2. AttributeError when trying to access result.stdout (which becomes None after the decode error)

Error Message

Exception in thread Thread-1 (_readerthread): Traceback (most recent call last): File "C:\Python311\Lib\threading.py", line 1038, in _bootstrap_inner self.run() File "C:\Python311\Lib\threading.py", line 975, in run self._target(*self._args, **self._kwargs) File "C:\Python311\Lib\subprocess.py", line 1597, in _readerthread self._out.write(b''.join(res)) File "<frozen codecs>", line 322, in decode UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 in position 8177: invalid continuation byte

Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\main.py", line 10160, in main args.func(args) File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\main.py", line 1522, in cmd_setup run_setup_wizard(args) File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\setup.py", line 3080, in run_setup_wizard _run_first_time_quick_setup(config, hermes_home, is_existing) File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\setup.py", line 3182, in _run_first_time_quick_setup setup_gateway(config) File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\setup.py", line 2405, in setup_gateway service_running = _is_service_running() File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\gateway.py", line 3186, in _is_service_running return len(find_gateway_pids()) > 0 File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\gateway.py", line 370, in find_gateway_pids for pid in _scan_gateway_pids(_exclude, all_profiles=all_profiles): File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\gateway.py", line 290, in _scan_gateway_pids for line in result.stdout.split("\n"): AttributeError: 'NoneType' object has no attribute 'split'

Root Cause

The _scan_gateway_pids() function in hermes_cli/gateway.py (lines 278-290) executes the Windows wmic command with text=True and encoding='utf-8' (implicit), but:

  1. wmic output is not UTF-8: On Windows systems, especially with non-English locales, wmic outputs text in the system's code page (e.g., cp936 for Chinese, cp1252 for Western European), NOT UTF-8.

  2. UnicodeDecodeError in subprocess: When Python tries to decode wmic's output as UTF-8, it fails if the output contains non-UTF-8 bytes (like 0xd0 at position 8177), causing the reader thread to crash.

  3. Cascading failure: After the decode error, result.stdout becomes None, leading to the AttributeError.

Current problematic code (lines 278-290):

if is_windows():
    result = subprocess.run(
        ["wmic", "process", "get", "ProcessId,CommandLine", "/FORMAT:LIST"],
        capture_output=True,
        text=True,  # ← Implicitly uses UTF-8 encoding
        timeout=10,
    )
    if result.returncode != 0:
        return []
    current_cmd = ""
    for line in result.stdout.split("\n"):  # ← stdout is None after decode error

Fix Action

Fixed

PR fix notes

PR #17073: fix(gateway): handle wmic UnicodeDecodeError gracefully

Description (problem / solution / changelog)

Summary

Fixes UnicodeDecodeError crash in Windows gateway process scanning by adding explicit encoding and error handling to the wmic subprocess.run call.

Root Cause

On Windows systems, especially with non-English locales, the wmic command outputs text in the system's code page (e.g., cp936 for Chinese, cp1252 for Western European), not UTF-8.

The current code in hermes_cli/gateway.py (lines 278-283) calls subprocess.run with text=True, which implicitly uses UTF-8 encoding. When wmic output contains non-UTF-8 bytes:

  1. Python's subprocess raises UnicodeDecodeError in the reader thread
  2. result.stdout becomes None after decode failure
  3. Line 287 crashes with AttributeError: 'NoneType' object has no attribute 'split'

Fix

  • Add explicit encoding='utf-8' to subprocess.run call
  • Add errors='ignore' to skip undecodable bytes instead of crashing
  • Check result.stdout is None before splitting to avoid AttributeError

This allows the setup wizard to continue gracefully on systems where wmic output cannot be fully decoded, returning an empty PID list instead of crashing.

Testing

  • Added regression test TestScanGatewayPids::test_handles_wmic_unicode_decode_error_gracefully that simulates decode failure (stdout=None) and verifies empty list is returned
  • Existing test test_find_gateway_pids_falls_back_to_pid_file_when_process_scan_fails still passes

Impact

  • Fixes crash during hermes setup on Windows with non-English locales
  • No functional regression: setup wizard continues with empty PID scan, which falls back to PID file discovery
  • Small, focused change: 3 lines in gateway.py, 1 test class

Fixes #17049

Changed files

  • hermes_cli/gateway.py (modified, +3/-1)
  • tests/hermes_cli/test_gateway.py (modified, +30/-5)

PR #17074: Fix UnicodeDecodeError in Windows wmic process scanning #17049

Description (problem / solution / changelog)

What does this PR do?

Fixes #17049 UnicodeDecodeError and AttributeError in Windows gateway process scanning.

Type of Change

  • Bug fix (non-breaking change which fixes an issue)
  • Critical (blocks hermes setup on Windows)

Related Issue

https://github.com/NousResearch/hermes-agent/issues/17049

Problem

The _scan_gateway_pids() function crashes on Windows systems with non-UTF-8 locales (e.g., Chinese cp936) because:

  1. wmic output uses system code page, not UTF-8: Windows wmic outputs text encoded in the system's locale code page, not UTF-8
  2. UnicodeDecodeError in subprocess reader: When Python tries to decode as UTF-8, it fails with UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0
  3. Cascading failure: The decode error causes result.stdout to become None, then AttributeError when trying to split it

This completely blocks hermes setup on affected Windows systems.

Solution

Added errors='ignore' parameter to the subprocess.run() call. This tells Python to skip undecodable bytes instead of crashing. For process scanning, losing a few non-UTF-8 characters is acceptable and doesn't affect functionality.

Also added a null check for result.stdout as defensive programming.

Changes Made

  • File: hermes_cli/gateway.py
  • Lines: 278-290 (Windows process scanning section)
  • Changes:
    1. Added errors='ignore' to handle non-UTF-8 bytes gracefully
    2. Added null check: or result.stdout is None in the early exit condition

Changed files

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

PR #1: fix: resolve 7 identified issues [automated]

Description (problem / solution / changelog)

Resumo

Este PR corrige 7 issues identificados no repositório NousResearch/hermes-agent.


Issues Corrigidos

1. #17086 - custom endpoint com api_mode=anthropic_messages falhava com 404

Arquivo: agent/auxiliary_client.py Problema: Quando provider=custom com api_mode=anthropic_messages e base_url terminando em /anthropic, a funcao _resolve_provider_client() convertia a URL para o formato /v1/messages, causando 404 em provedores Anthropic-compatíveis de terceiros. Correcao: Mantem o path /anthropic quando api_mode=anthropic_messages e o base_url ja termina em /anthropic.


2. #17076 - kimi-coding vision quebrado (404 em analise de imagem)

Arquivo: agent/auxiliary_client.py Problema: kimi-coding nao estava listado em _PROVIDER_VISION_MODELS, entao auxiliary.vision.provider: auto nao conseguia detectar o modelo de visao disponivel para Kimi. Correcao: Adicionado kimi-coding e kimi-coding-cn ao mapa de modelos de visao.


3. #17080 - hermes profile create --clone copiava credenciais exclusivas de plataforma

Arquivo: hermes_cli/profiles.py Problema: O clone de perfil copiava TELEGRAM_BOT_TOKEN, DISCORD_BOT_TOKEN, WEIXIN_TOKEN verbatim. Quando dois perfis iniciam simultaneamente com o mesmo token, o adaptador de plataforma falha durante a aquisicao de lock. Correcao: Define _EXCLUSIVE_PLATFORM_KEYS e _EXCLUSIVE_PLATFORM_CONFIG_PATHS. Credenciais exclusivas sao comentadas em .env e entradas de plataforma sao enabled: false em config.yaml apos clone.


4. #17054 - Slack manifest rejeitava nomes com underscore

Arquivo: hermes_cli/commands.py Problema: _sanitize_slack_name() convertia nomes de comandos como _reload_mcp para Slack mas nao removia o prefixo underscore, causando rejeicao do manifest. Correcao: Adicionada verificacao para pular nomes que começam com underscore antes de adicionar a lista de slash commands.


5. #17057 - custom Kimi-compatible endpoint falhava apos tool call com thinking habilitado

Arquivo: run_agent.py Problema: _needs_kimi_tool_reasoning() só verificava hostnames oficiais (api.kimi.com, moonshot.ai, moonshot.cn). Endpoints Kimi-compatíveis customizados nao eram detectados. Correcao: Ampliada a verificacao para detectar endpoints customizados pela familia do modelo (nome contem "kimi" ou "k2") alem do hostname.


6. #17049 - UnicodeDecodeError no scan de processos Windows (wmic)

Arquivo: hermes_cli/gateway.py Problema: wmic emitia saida em encoding local do Windows (cp1252/utf-16), causando UnicodeDecodeError e AttributeError durante parsing. Correcao: O parsing agora usa errors=ignore no decode, tratando bytes invalidos como despreziveis.


7. #17052 - stale reasoning reutilizado quando turn atual nao tem reasoning_content

Arquivo: run_agent.py Problema: Mensagens de assistant com tool_calls e reasoning_content eram reutilizadas indevidamente em turns que nao tinham reasoning_content, causando confabulacoes em provedores como Qwen3.6:27b via Ollama. Correcao: O loop de replay agora detecta quando a mensagem atual e um assistant com tool_calls mas sem reasoning_content, e limpa msg[reasoning_content] e msg[reasoning] para evitar propagacao de estado de reasoning de turns anteriores.


Arquivos Modificados

  • agent/auxiliary_client.py - #17086, #17076
  • hermes_cli/profiles.py - #17080
  • hermes_cli/commands.py - #17054
  • run_agent.py - #17057, #17052
  • hermes_cli/gateway.py - #17049

Notas

  • Este PR contem 8 commits (7 issues + 1 fix de seguranca do upstream relacionado a redaction de secrets)
  • Todos os commits foram feitos na branch fix-7-issues-clean
  • Nenhum push intermediario foi feito - push unico ao final
  • Commits do upstream incluidos para manter o historico completo: #16843, #17041, #17039

Changed files

  • .gitignore (modified, +1/-0)
  • Dockerfile (modified, +6/-2)
  • acp_adapter/entry.py (modified, +11/-0)
  • acp_adapter/server.py (modified, +28/-1)
  • agent/anthropic_adapter.py (modified, +134/-74)
  • agent/auxiliary_client.py (modified, +325/-53)
  • agent/bedrock_adapter.py (modified, +41/-3)
  • agent/context_compressor.py (modified, +113/-5)
  • agent/credential_pool.py (modified, +82/-4)
  • agent/credential_sources.py (modified, +0/-1)
  • agent/error_classifier.py (modified, +32/-0)
  • agent/gemini_cloudcode_adapter.py (modified, +0/-2)
  • agent/gemini_schema.py (modified, +1/-1)
  • agent/google_code_assist.py (modified, +0/-1)
  • agent/google_oauth.py (modified, +3/-3)
  • agent/image_routing.py (added, +236/-0)
  • agent/memory_manager.py (modified, +113/-5)
  • agent/model_metadata.py (modified, +56/-21)
  • agent/nous_rate_guard.py (modified, +144/-1)
  • agent/onboarding.py (added, +191/-0)
  • agent/prompt_builder.py (modified, +38/-0)
  • agent/redact.py (modified, +13/-6)
  • agent/shell_hooks.py (modified, +7/-2)
  • agent/skill_commands.py (modified, +2/-2)
  • agent/title_generator.py (modified, +39/-5)
  • agent/transports/anthropic.py (modified, +1/-7)
  • agent/transports/chat_completions.py (modified, +74/-0)
  • agent/transports/codex.py (modified, +1/-3)
  • cli-config.yaml.example (modified, +28/-8)
  • cli.py (modified, +522/-195)
  • cron/jobs.py (modified, +34/-5)
  • cron/scheduler.py (modified, +39/-5)
  • docker/entrypoint.sh (modified, +9/-7)
  • flake.nix (modified, +1/-0)
  • gateway/channel_directory.py (modified, +67/-14)
  • gateway/config.py (modified, +84/-3)
  • gateway/display_config.py (modified, +3/-1)
  • gateway/mirror.py (modified, +57/-11)
  • gateway/pairing.py (modified, +2/-1)
  • gateway/platforms/__init__.py (modified, +2/-0)
  • gateway/platforms/base.py (modified, +233/-16)
  • gateway/platforms/discord.py (modified, +18/-24)
  • gateway/platforms/email.py (modified, +3/-0)
  • gateway/platforms/feishu_comment.py (modified, +0/-1)
  • gateway/platforms/helpers.py (modified, +11/-2)
  • gateway/platforms/matrix.py (modified, +493/-47)
  • gateway/platforms/mattermost.py (modified, +0/-1)
  • gateway/platforms/qqbot/adapter.py (modified, +2/-7)
  • gateway/platforms/slack.py (modified, +753/-70)
  • gateway/platforms/telegram.py (modified, +138/-14)
  • gateway/platforms/weixin.py (modified, +26/-3)
  • gateway/platforms/yuanbao.py (added, +4754/-0)
  • gateway/platforms/yuanbao_media.py (added, +645/-0)
  • gateway/platforms/yuanbao_proto.py (added, +1209/-0)
  • gateway/platforms/yuanbao_sticker.py (added, +558/-0)
  • gateway/run.py (modified, +1143/-283)
  • gateway/runtime_footer.py (added, +150/-0)
  • gateway/session.py (modified, +16/-21)
  • gateway/stream_consumer.py (modified, +110/-0)
  • gateway/whatsapp_identity.py (modified, +21/-1)
  • hermes_cli/auth.py (modified, +40/-4)
  • hermes_cli/azure_detect.py (modified, +1/-1)
  • hermes_cli/backup.py (modified, +272/-1)
  • hermes_cli/banner.py (modified, +0/-1)
  • hermes_cli/claw.py (modified, +67/-6)
  • hermes_cli/commands.py (modified, +119/-5)
  • hermes_cli/config.py (modified, +322/-29)
  • hermes_cli/debug.py (modified, +13/-7)
  • hermes_cli/dingtalk_auth.py (modified, +0/-1)
  • hermes_cli/doctor.py (modified, +11/-1)
  • hermes_cli/env_loader.py (modified, +2/-1)
  • hermes_cli/fallback_cmd.py (added, +361/-0)
  • hermes_cli/gateway.py (modified, +47/-12)
  • hermes_cli/hooks.py (modified, +1/-2)
  • hermes_cli/main.py (modified, +691/-58)
  • hermes_cli/model_catalog.py (added, +329/-0)
  • hermes_cli/model_switch.py (modified, +55/-6)
  • hermes_cli/models.py (modified, +251/-43)
  • hermes_cli/nous_subscription.py (modified, +16/-8)
  • hermes_cli/oneshot.py (modified, +28/-11)
  • hermes_cli/platforms.py (modified, +1/-0)
  • hermes_cli/plugins.py (modified, +14/-0)
  • hermes_cli/plugins_cmd.py (modified, +0/-1)
  • hermes_cli/profiles.py (modified, +199/-4)
  • hermes_cli/providers.py (modified, +26/-0)
  • hermes_cli/runtime_provider.py (modified, +100/-14)
  • hermes_cli/setup.py (modified, +69/-16)
  • hermes_cli/skills_hub.py (modified, +230/-20)
  • hermes_cli/slack_cli.py (added, +152/-0)
  • hermes_cli/status.py (modified, +3/-2)
  • hermes_cli/timeouts.py (modified, +4/-4)
  • hermes_cli/tips.py (modified, +2/-3)
  • hermes_cli/tools_config.py (modified, +173/-4)
  • hermes_cli/web_server.py (modified, +11/-14)
  • hermes_cli/webhook.py (modified, +2/-2)
  • hermes_logging.py (modified, +3/-4)
  • hermes_state.py (modified, +578/-164)
  • model_tools.py (modified, +45/-10)
  • nix/checks.nix (modified, +30/-3)
  • nix/hermes-agent.nix (added, +186/-0)

PR #17090: fix: resolve 7 identified issues [automated]

Description (problem / solution / changelog)

Resumo

Este PR corrige 7 issues identificados no repositório NousResearch/hermes-agent.


Issues Corrigidos

1. #17086 - custom endpoint com api_mode=anthropic_messages falhava com 404

Arquivo: agent/auxiliary_client.py Problema: Quando provider=custom com api_mode=anthropic_messages e base_url terminando em /anthropic, a funcao _resolve_provider_client() convertia a URL para o formato /v1/messages, causando 404 em provedores Anthropic-compatíveis de terceiros. Correcao: Mantem o path /anthropic quando api_mode=anthropic_messages e o base_url ja termina em /anthropic.


2. #17076 - kimi-coding vision quebrado (404 em analise de imagem)

Arquivo: agent/auxiliary_client.py Problema: kimi-coding nao estava listado em _PROVIDER_VISION_MODELS, entao auxiliary.vision.provider: auto nao conseguia detectar o modelo de visao disponivel para Kimi. Correcao: Adicionado kimi-coding e kimi-coding-cn ao mapa de modelos de visao.


3. #17080 - hermes profile create --clone copiava credenciais exclusivas de plataforma

Arquivo: hermes_cli/profiles.py Problema: O clone de perfil copiava TELEGRAM_BOT_TOKEN, DISCORD_BOT_TOKEN, WEIXIN_TOKEN verbatim. Quando dois perfis iniciam simultaneamente com o mesmo token, o adaptador de plataforma falha durante a aquisicao de lock. Correcao: Define _EXCLUSIVE_PLATFORM_KEYS e _EXCLUSIVE_PLATFORM_CONFIG_PATHS. Credenciais exclusivas sao comentadas em .env e entradas de plataforma sao enabled: false em config.yaml apos clone.


4. #17054 - Slack manifest rejeitava nomes com underscore

Arquivo: hermes_cli/commands.py Problema: _sanitize_slack_name() convertia nomes de comandos como _reload_mcp para Slack mas nao removia o prefixo underscore, causando rejeicao do manifest. Correcao: Adicionada verificacao para pular nomes que começam com underscore antes de adicionar a lista de slash commands.


5. #17057 - custom Kimi-compatible endpoint falhava apos tool call com thinking habilitado

Arquivo: run_agent.py Problema: _needs_kimi_tool_reasoning() só verificava hostnames oficiais (api.kimi.com, moonshot.ai, moonshot.cn). Endpoints Kimi-compatíveis customizados nao eram detectados. Correcao: Ampliada a verificacao para detectar endpoints customizados pela familia do modelo (nome contem "kimi" ou "k2") alem do hostname.


6. #17049 - UnicodeDecodeError no scan de processos Windows (wmic)

Arquivo: hermes_cli/gateway.py Problema: wmic emitia saida em encoding local do Windows (cp1252/utf-16), causando UnicodeDecodeError e AttributeError durante parsing. Correcao: O parsing agora usa errors=ignore no decode, tratando bytes invalidos como despreziveis.


7. #17052 - stale reasoning reutilizado quando turn atual nao tem reasoning_content

Arquivo: run_agent.py Problema: Mensagens de assistant com tool_calls e reasoning_content eram reutilizadas indevidamente em turns que nao tinham reasoning_content, causando confabulacoes em provedores como Qwen3.6:27b via Ollama. Correcao: O loop de replay agora detecta quando a mensagem atual e um assistant com tool_calls mas sem reasoning_content, e limpa msg[reasoning_content] e msg[reasoning] para evitar propagacao de estado de reasoning de turns anteriores.


Arquivos Modificados

  • agent/auxiliary_client.py - #17086, #17076
  • hermes_cli/profiles.py - #17080
  • hermes_cli/commands.py - #17054
  • run_agent.py - #17057, #17052
  • hermes_cli/gateway.py - #17049

Notas

  • Este PR contem 8 commits (7 issues + 1 fix de seguranca do upstream relacionado a redaction de secrets)
  • Todos os commits foram feitos na branch fix-7-issues-clean
  • Nenhum push intermediario foi feito - push unico ao final
  • Commits do upstream incluidos para manter o historico completo: #16843, #17041, #17039

Changed files

  • agent/auxiliary_client.py (modified, +36/-0)
  • agent/redact.py (modified, +6/-3)
  • gateway/run.py (modified, +10/-4)
  • hermes_cli/commands.py (modified, +3/-0)
  • hermes_cli/gateway.py (modified, +22/-8)
  • hermes_cli/main.py (modified, +18/-7)
  • hermes_cli/profiles.py (modified, +141/-2)
  • run_agent.py (modified, +33/-9)
  • tools/terminal_tool.py (modified, +10/-2)

PR #17123: fix(update): protect dashboard wmic scan against UnicodeDecodeError on Windows non-UTF-8 locales (#17049)

Description (problem / solution / changelog)

Summary

  • hermes update's _warn_stale_dashboard_processes() shells out to wmic with text=True and no encoding=, so on Windows non-UTF-8 locales (e.g. cp936) the subprocess reader thread crashes with UnicodeDecodeError, leaves result.stdout = None, and hermes update aborts with the exact AttributeError: 'NoneType' object has no attribute 'split' reported in #17049.
  • Pass encoding="utf-8", errors="ignore" (matching the ASCII-only key parsing the function does), and add a result.stdout is None defensive guard.
  • New regression tests reproduce the AttributeError on clean main and pass with the fix.

The bug

The reported #17049 stack trace lists two errors stacked:

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 ...   (reader thread)
...
File "hermes_cli/gateway.py", line 290, in _scan_gateway_pids
  for line in result.stdout.split("\n"):
AttributeError: 'NoneType' object has no attribute 'split'      (main thread)

The same buggy pattern exists in two places:

File:lineFunctionTriggered by
hermes_cli/gateway.py:279_scan_gateway_pidshermes setup
hermes_cli/main.py:5239_warn_stale_dashboard_processeshermes update

#17074 patches the gateway one. This PR patches the second one. Until both land, Chinese-locale (and other non-UTF-8) Windows users remain unable to run hermes update — they hit the AttributeError before the upgrade can warn-or-skip its way to completion.

The fix

hermes_cli/main.py:

result = subprocess.run(
    ["wmic", "process", "get", "ProcessId,CommandLine", "/FORMAT:LIST"],
    capture_output=True, text=True, timeout=10,
    encoding="utf-8", errors="ignore",
)
if result.returncode != 0 or result.stdout is None:
    return
  • errors="ignore" is safe here because the parser only matches the literal ASCII prefixes CommandLine= and ProcessId=. Dropping undecodable bytes can never produce a false positive PID match — and it cannot regress the existing tests, which all use plain ASCII fixtures.
  • The is None guard is defensive cover for any future / older Python where the reader thread still fails for some other reason.

Test plan

  • Focused regression tests added (tests/hermes_cli/test_update_stale_dashboard.py::TestWindowsWmicEncoding):
    • test_wmic_invoked_with_utf8_ignore_errors — asserts subprocess.run is called with encoding="utf-8", errors="ignore".
    • test_wmic_returns_none_stdout_does_not_crash — simulates the post-decode-crash result.stdout=None state and asserts no AttributeError.
  • Both new tests fail against clean origin/main (7d4648461) with AttributeError: 'NoneType' object has no attribute 'split' (the exact error from #17049), proving the regression guard.
  • All 10 existing _warn_stale_dashboard_processes tests still pass.
  • Adjacent suites: tests/hermes_cli/test_cmd_update.py, test_update_autostash.py, test_update_check.py, test_update_gateway_restart.py, test_update_hangup_protection.py, test_update_config_clears_custom_fields.py — 93 pass; the 3 unrelated failures (test_update_refreshes_repo_and_tui_node_dependencies, test_cmd_update_succeeds_with_extras, test_cmd_update_retries_optional_extras_individually_when_all_fails) reproduce identically on clean origin/main and do not touch the wmic scan.

Related / Positioning

PRScopeDifference
#17074 (oyoyo)hermes_cli/gateway.py::_scan_gateway_pidsFixes the hermes setup callsite; gateway PID detection.
This PRhermes_cli/main.py::_warn_stale_dashboard_processesFixes the hermes update callsite; dashboard staleness warning. Adds a Windows-locale regression test (the existing test file only covered the macOS/Linux ps branch).

Same root cause, two callsites — these are intentionally separate, complementary PRs. There is no overlap in touched lines.

Related

  • Fixes #17049 (in conjunction with #17074)

Changed files

  • hermes_cli/main.py (modified, +9/-1)
  • tests/hermes_cli/test_update_stale_dashboard.py (modified, +52/-0)

PR #17134: fix: resolve 4 identified issues [automated]

Description (problem / solution / changelog)

Fixes #16974, #17091, #17009, #17049

Changed files

  • Dockerfile (modified, +2/-1)
  • agent/context_compressor.py (modified, +462/-51)
  • agent/transports/chat_completions.py (modified, +11/-0)
  • cli.py (modified, +13/-2)
  • cron/scheduler.py (modified, +5/-6)
  • gateway/platforms/discord.py (modified, +20/-7)
  • gateway/platforms/feishu.py (modified, +26/-7)
  • gateway/run.py (modified, +90/-31)
  • gateway/status.py (modified, +8/-1)
  • hermes_cli/commands.py (modified, +22/-1)
  • hermes_cli/config.py (modified, +1/-1)
  • hermes_cli/copilot_auth.py (modified, +1/-1)
  • hermes_cli/gateway.py (modified, +4/-0)
  • hermes_cli/main.py (modified, +94/-5)
  • hermes_cli/web_server.py (modified, +1/-1)
  • model_tools.py (modified, +44/-13)
  • run_agent.py (modified, +326/-55)
  • skills/red-teaming/godmode/scripts/load_godmode.py (modified, +9/-8)
  • tests/agent/test_context_compressor.py (modified, +389/-0)
  • tests/gateway/test_compress_command.py (modified, +49/-0)
  • tests/run_agent/test_413_compression.py (modified, +81/-1)
  • tests/run_agent/test_compression_boundary_hook.py (modified, +42/-0)
  • tests/run_agent/test_run_agent.py (modified, +100/-13)
  • tools/session_search_tool.py (modified, +2/-2)
  • tui_gateway/server.py (modified, +4/-3)
  • ui-tui/src/app/turnController.ts (modified, +1/-1)

PR #3: fix: resolve 7 identified issues [automated]

Description (problem / solution / changelog)

Summary

This PR resolves 7 issues identified in the NousResearch/hermes-agent upstream repository.

Issues Fixed

#17139 - Cron Telegram deliver=['telegram'] fails

File: cron/scheduler.py Problem: When deliver is specified as a list (e.g., ['telegram']), the scheduler used str(deliver).split(",") which converted it to "['telegram']" instead of parsing the list items. Fix: Added check isinstance(deliver, list) to properly handle list-format delivery targets.

#17086 - Custom endpoint URL rewrite strips /anthropic path

File: agent/auxiliary_client.py Problem: Custom endpoints with api_mode: anthropic_messages had URLs rewritten from /anthropic to /v1, causing 404 errors. Fix: Added api_mode != "anthropic_messages" guard to skip URL rewriting when using Anthropic-native message format.

#17054 - Slack manifest broken metadata

File: hermes_cli/slack_cli.py Problem: Slack manifest used "major_version": 1, "minor_version": 1 which is invalid for v1 manifests. Fix: Changed to use "version": "2.0.0" format.

#17049 - Windows wmic UnicodeDecodeError

File: hermes_cli/gateway.py Problem: wmic command output on Windows uses system code page, not UTF-8, causing UnicodeDecodeError and cascading AttributeError on result.stdout. Fix: Added encoding="utf-8", errors="replace" to subprocess call and OSError exception handling.

#17043 - TelegramFallbackTransport DoH drops IPs

File: gateway/platforms/telegram_network.py Problem: discover_fallback_ips() filtered out DoH-resolved IPs that matched system DNS, causing fallback to hardcoded seed IPs on networks where seed IPs aren't routable. Fix: Removed ip not in system_ips exclusion - DoH-confirmed IPs are now preserved.

#17140 - TTS tools use os.getenv() instead of get_env_value()

File: tools/tts_tool.py Problem: TTS providers (elevenlabs, minimax, mistral, xai, gemini) used os.getenv() which doesn't read values from ~/.hermes/.env loaded via the hermes config bridge. Fix: Replaced with get_env_value() calls for all TTS API keys.

hermes_cli/config.py - _sanitize_env_lines KEY= detection

File: hermes_cli/config.py Problem: _sanitize_env_lines matched KEY= patterns that appeared as substrings within other keys (e.g., LM_API_KEY matched inside GLM_API_KEY). Fix: Only treat KEY= as a separator when it appears at position 0 or after a non-identifier character.

Files Modified

  • agent/auxiliary_client.py (+289 lines)
  • cron/scheduler.py (+21 lines)
  • gateway/platforms/telegram_network.py (+9 lines)
  • hermes_cli/config.py (+259 lines)
  • hermes_cli/gateway.py (+21 lines)
  • hermes_cli/slack_cli.py (+3 lines)
  • tools/tts_tool.py (+43 lines)

Testing

All fixes are focused on bug corrections with minimal behavioral changes. The existing test suite should pass.


Automated PR created by Hermes Agent cron job

Changed files

  • .gitignore (modified, +1/-0)
  • Dockerfile (modified, +8/-3)
  • agent/auxiliary_client.py (modified, +344/-55)
  • agent/context_compressor.py (modified, +509/-54)
  • agent/credential_pool.py (modified, +6/-3)
  • agent/error_classifier.py (modified, +31/-0)
  • agent/image_routing.py (added, +236/-0)
  • agent/memory_manager.py (modified, +114/-5)
  • agent/model_metadata.py (modified, +51/-21)
  • agent/nous_rate_guard.py (modified, +142/-0)
  • agent/onboarding.py (added, +191/-0)
  • agent/prompt_builder.py (modified, +34/-0)
  • agent/shell_hooks.py (modified, +5/-1)
  • agent/skill_commands.py (modified, +2/-2)
  • agent/title_generator.py (modified, +33/-4)
  • agent/transports/chat_completions.py (modified, +11/-0)
  • cli-config.yaml.example (modified, +28/-8)
  • cli.py (modified, +466/-196)
  • cron/jobs.py (modified, +31/-3)
  • cron/scheduler.py (modified, +44/-6)
  • docker/entrypoint.sh (modified, +9/-7)
  • flake.nix (modified, +1/-0)
  • gateway/channel_directory.py (modified, +67/-14)
  • gateway/config.py (modified, +68/-2)
  • gateway/display_config.py (modified, +3/-1)
  • gateway/mirror.py (modified, +57/-11)
  • gateway/platforms/__init__.py (modified, +2/-0)
  • gateway/platforms/base.py (modified, +152/-5)
  • gateway/platforms/discord.py (modified, +24/-28)
  • gateway/platforms/email.py (modified, +3/-0)
  • gateway/platforms/feishu.py (modified, +26/-7)
  • gateway/platforms/helpers.py (modified, +9/-0)
  • gateway/platforms/matrix.py (modified, +73/-3)
  • gateway/platforms/slack.py (modified, +753/-70)
  • gateway/platforms/telegram.py (modified, +45/-0)
  • gateway/platforms/telegram_network.py (modified, +7/-2)
  • gateway/platforms/yuanbao.py (added, +4754/-0)
  • gateway/platforms/yuanbao_media.py (added, +647/-0)
  • gateway/platforms/yuanbao_proto.py (added, +1210/-0)
  • gateway/platforms/yuanbao_sticker.py (added, +558/-0)
  • gateway/run.py (modified, +745/-259)
  • gateway/session.py (modified, +11/-2)
  • gateway/status.py (modified, +8/-1)
  • gateway/stream_consumer.py (modified, +110/-0)
  • gateway/whatsapp_identity.py (modified, +21/-1)
  • hermes_cli/auth.py (modified, +28/-3)
  • hermes_cli/backup.py (modified, +177/-1)
  • hermes_cli/commands.py (modified, +113/-5)
  • hermes_cli/config.py (modified, +349/-34)
  • hermes_cli/copilot_auth.py (modified, +1/-1)
  • hermes_cli/debug.py (modified, +11/-5)
  • hermes_cli/doctor.py (modified, +2/-0)
  • hermes_cli/fallback_cmd.py (added, +361/-0)
  • hermes_cli/gateway.py (modified, +35/-10)
  • hermes_cli/main.py (modified, +577/-30)
  • hermes_cli/model_catalog.py (added, +329/-0)
  • hermes_cli/models.py (modified, +98/-6)
  • hermes_cli/nous_subscription.py (modified, +16/-8)
  • hermes_cli/platforms.py (modified, +1/-0)
  • hermes_cli/providers.py (modified, +11/-0)
  • hermes_cli/runtime_provider.py (modified, +31/-0)
  • hermes_cli/setup.py (modified, +69/-14)
  • hermes_cli/skills_hub.py (modified, +230/-20)
  • hermes_cli/slack_cli.py (added, +151/-0)
  • hermes_cli/status.py (modified, +2/-1)
  • hermes_cli/timeouts.py (modified, +4/-4)
  • hermes_cli/tips.py (modified, +2/-3)
  • hermes_cli/tools_config.py (modified, +14/-3)
  • hermes_cli/web_server.py (modified, +8/-10)
  • hermes_logging.py (modified, +3/-4)
  • hermes_state.py (modified, +319/-63)
  • model_tools.py (modified, +44/-13)
  • nix/checks.nix (modified, +30/-3)
  • nix/hermes-agent.nix (added, +186/-0)
  • nix/nixosModules.nix (modified, +81/-6)
  • nix/overlays.nix (added, +10/-0)
  • nix/packages.nix (modified, +6/-107)
  • nix/python.nix (modified, +2/-1)
  • nix/tui.nix (modified, +2/-1)
  • optional-skills/creative/touchdesigner-mcp/SKILL.md (modified, +7/-1)
  • optional-skills/creative/touchdesigner-mcp/references/audio-reactive.md (added, +175/-0)
  • optional-skills/creative/touchdesigner-mcp/references/geometry-comp.md (added, +121/-0)
  • optional-skills/creative/touchdesigner-mcp/references/glsl.md (added, +151/-0)
  • optional-skills/creative/touchdesigner-mcp/references/layout-compositor.md (added, +131/-0)
  • optional-skills/creative/touchdesigner-mcp/references/operator-tips.md (added, +106/-0)
  • optional-skills/creative/touchdesigner-mcp/references/pitfalls.md (modified, +221/-25)
  • optional-skills/creative/touchdesigner-mcp/references/postfx.md (added, +183/-0)
  • optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py (modified, +27/-2)
  • plugins/google_meet/README.md (added, +131/-0)
  • plugins/google_meet/SKILL.md (added, +148/-0)
  • plugins/google_meet/__init__.py (added, +103/-0)
  • plugins/google_meet/audio_bridge.py (added, +244/-0)
  • plugins/google_meet/cli.py (added, +478/-0)
  • plugins/google_meet/meet_bot.py (added, +852/-0)
  • plugins/google_meet/node/__init__.py (added, +54/-0)
  • plugins/google_meet/node/cli.py (added, +125/-0)
  • plugins/google_meet/node/client.py (added, +107/-0)
  • plugins/google_meet/node/protocol.py (added, +124/-0)
  • plugins/google_meet/node/registry.py (added, +112/-0)
  • plugins/google_meet/node/server.py (added, +193/-0)

PR #16165: fix: resolve 7 identified issues [automated]

Description (problem / solution / changelog)

Summary

This PR resolves 7 issues identified in the NousResearch/hermes-agent upstream repository.

Issues Fixed

#17139 - Cron Telegram deliver=['telegram'] fails

File: cron/scheduler.py Problem: When deliver is specified as a list (e.g., ['telegram']), the scheduler used str(deliver).split(",") which converted it to "['telegram']" instead of parsing the list items. Fix: Added check isinstance(deliver, list) to properly handle list-format delivery targets.

#17086 - Custom endpoint URL rewrite strips /anthropic path

File: agent/auxiliary_client.py Problem: Custom endpoints with api_mode: anthropic_messages had URLs rewritten from /anthropic to /v1, causing 404 errors. Fix: Added api_mode != "anthropic_messages" guard to skip URL rewriting when using Anthropic-native message format.

#17054 - Slack manifest broken metadata

File: hermes_cli/slack_cli.py Problem: Slack manifest used "major_version": 1, "minor_version": 1 which is invalid for v1 manifests. Fix: Changed to use "version": "2.0.0" format.

#17049 - Windows wmic UnicodeDecodeError

File: hermes_cli/gateway.py Problem: wmic command output on Windows uses system code page, not UTF-8, causing UnicodeDecodeError and cascading AttributeError on result.stdout. Fix: Added encoding="utf-8", errors="replace" to subprocess call and OSError exception handling.

#17043 - TelegramFallbackTransport DoH drops IPs

File: gateway/platforms/telegram_network.py Problem: discover_fallback_ips() filtered out DoH-resolved IPs that matched system DNS, causing fallback to hardcoded seed IPs on networks where seed IPs aren't routable. Fix: Removed ip not in system_ips exclusion - DoH-confirmed IPs are now preserved.

#17140 - TTS tools use os.getenv() instead of get_env_value()

File: tools/tts_tool.py Problem: TTS providers (elevenlabs, minimax, mistral, xai, gemini) used os.getenv() which doesn't read values from ~/.hermes/.env loaded via the hermes config bridge. Fix: Replaced with get_env_value() calls for all TTS API keys.

hermes_cli/config.py - _sanitize_env_lines KEY= detection

File: hermes_cli/config.py Problem: _sanitize_env_lines matched KEY= patterns that appeared as substrings within other keys (e.g., LM_API_KEY matched inside GLM_API_KEY). Fix: Only treat KEY= as a separator when it appears at position 0 or after a non-identifier character.

Files Modified

  • agent/auxiliary_client.py
  • cron/scheduler.py
  • gateway/platforms/telegram_network.py
  • hermes_cli/config.py
  • hermes_cli/gateway.py
  • hermes_cli/slack_cli.py
  • tools/tts_tool.py

Automated PR updated by Hermes Agent cron job

Changed files

  • .gitignore (modified, +1/-0)
  • Dockerfile (modified, +8/-3)
  • agent/auxiliary_client.py (modified, +344/-55)
  • agent/context_compressor.py (modified, +509/-54)
  • agent/error_classifier.py (modified, +31/-0)
  • agent/image_routing.py (added, +236/-0)
  • agent/memory_manager.py (modified, +114/-5)
  • agent/model_metadata.py (modified, +35/-16)
  • agent/onboarding.py (modified, +52/-5)
  • agent/prompt_builder.py (modified, +34/-0)
  • agent/shell_hooks.py (modified, +5/-1)
  • agent/title_generator.py (modified, +33/-4)
  • agent/transports/chat_completions.py (modified, +11/-0)
  • cli-config.yaml.example (modified, +6/-1)
  • cli.py (modified, +390/-58)
  • cron/jobs.py (modified, +31/-3)
  • cron/scheduler.py (modified, +41/-3)
  • flake.nix (modified, +1/-0)
  • gateway/channel_directory.py (modified, +67/-14)
  • gateway/config.py (modified, +68/-2)
  • gateway/display_config.py (modified, +3/-1)
  • gateway/mirror.py (modified, +57/-11)
  • gateway/platforms/__init__.py (modified, +2/-0)
  • gateway/platforms/base.py (modified, +117/-0)
  • gateway/platforms/discord.py (modified, +24/-23)
  • gateway/platforms/email.py (modified, +3/-0)
  • gateway/platforms/feishu.py (modified, +26/-7)
  • gateway/platforms/helpers.py (modified, +9/-0)
  • gateway/platforms/matrix.py (modified, +73/-3)
  • gateway/platforms/slack.py (modified, +753/-70)
  • gateway/platforms/telegram.py (modified, +45/-0)
  • gateway/platforms/telegram_network.py (modified, +7/-2)
  • gateway/platforms/yuanbao.py (added, +4754/-0)
  • gateway/platforms/yuanbao_media.py (added, +647/-0)
  • gateway/platforms/yuanbao_proto.py (added, +1210/-0)
  • gateway/platforms/yuanbao_sticker.py (added, +558/-0)
  • gateway/run.py (modified, +570/-60)
  • gateway/session.py (modified, +11/-2)
  • gateway/status.py (modified, +8/-1)
  • gateway/stream_consumer.py (modified, +110/-0)
  • gateway/whatsapp_identity.py (modified, +21/-1)
  • hermes_cli/auth.py (modified, +9/-0)
  • hermes_cli/backup.py (modified, +177/-1)
  • hermes_cli/commands.py (modified, +112/-2)
  • hermes_cli/config.py (modified, +358/-34)
  • hermes_cli/copilot_auth.py (modified, +1/-1)
  • hermes_cli/debug.py (modified, +11/-5)
  • hermes_cli/doctor.py (modified, +2/-0)
  • hermes_cli/gateway.py (modified, +35/-10)
  • hermes_cli/main.py (modified, +530/-28)
  • hermes_cli/models.py (modified, +70/-5)
  • hermes_cli/nous_subscription.py (modified, +16/-8)
  • hermes_cli/platforms.py (modified, +1/-0)
  • hermes_cli/providers.py (modified, +11/-0)
  • hermes_cli/runtime_provider.py (modified, +31/-0)
  • hermes_cli/setup.py (modified, +69/-14)
  • hermes_cli/skills_hub.py (modified, +170/-6)
  • hermes_cli/slack_cli.py (added, +151/-0)
  • hermes_cli/status.py (modified, +2/-1)
  • hermes_cli/timeouts.py (modified, +4/-4)
  • hermes_cli/tips.py (modified, +1/-1)
  • hermes_cli/tools_config.py (modified, +14/-3)
  • hermes_cli/web_server.py (modified, +8/-10)
  • hermes_logging.py (modified, +3/-4)
  • hermes_state.py (modified, +307/-62)
  • model_tools.py (modified, +44/-13)
  • nix/checks.nix (modified, +30/-3)
  • nix/hermes-agent.nix (added, +186/-0)
  • nix/nixosModules.nix (modified, +81/-6)
  • nix/overlays.nix (added, +10/-0)
  • nix/packages.nix (modified, +6/-107)
  • nix/python.nix (modified, +2/-1)
  • nix/tui.nix (modified, +2/-1)
  • optional-skills/creative/touchdesigner-mcp/SKILL.md (modified, +7/-1)
  • optional-skills/creative/touchdesigner-mcp/references/audio-reactive.md (added, +175/-0)
  • optional-skills/creative/touchdesigner-mcp/references/geometry-comp.md (added, +121/-0)
  • optional-skills/creative/touchdesigner-mcp/references/glsl.md (added, +151/-0)
  • optional-skills/creative/touchdesigner-mcp/references/layout-compositor.md (added, +131/-0)
  • optional-skills/creative/touchdesigner-mcp/references/operator-tips.md (added, +106/-0)
  • optional-skills/creative/touchdesigner-mcp/references/pitfalls.md (modified, +221/-25)
  • optional-skills/creative/touchdesigner-mcp/references/postfx.md (added, +183/-0)
  • optional-skills/migration/openclaw-migration/scripts/openclaw_to_hermes.py (modified, +27/-2)
  • plugins/google_meet/README.md (added, +131/-0)
  • plugins/google_meet/SKILL.md (added, +148/-0)
  • plugins/google_meet/__init__.py (added, +103/-0)
  • plugins/google_meet/audio_bridge.py (added, +244/-0)
  • plugins/google_meet/cli.py (added, +478/-0)
  • plugins/google_meet/meet_bot.py (added, +852/-0)
  • plugins/google_meet/node/__init__.py (added, +54/-0)
  • plugins/google_meet/node/cli.py (added, +125/-0)
  • plugins/google_meet/node/client.py (added, +107/-0)
  • plugins/google_meet/node/protocol.py (added, +124/-0)
  • plugins/google_meet/node/registry.py (added, +112/-0)
  • plugins/google_meet/node/server.py (added, +193/-0)
  • plugins/google_meet/plugin.yaml (added, +16/-0)
  • plugins/google_meet/process_manager.py (added, +326/-0)
  • plugins/google_meet/realtime/__init__.py (added, +10/-0)
  • plugins/google_meet/realtime/openai_client.py (added, +332/-0)
  • plugins/google_meet/tools.py (added, +348/-0)
  • plugins/memory/hindsight/__init__.py (modified, +154/-43)

PR #17252: fix(gateway): handle wmic encoding errors on Windows non-English locales

Description (problem / solution / changelog)

Summary

Fix UnicodeDecodeError and cascading AttributeError in Windows gateway process scanning on non-English locales.

Problem

On Windows systems with non-English locales, wmic outputs text in the system code page (e.g. cp936 for Chinese, cp1252 for Western European) rather than UTF-8. When Python's subprocess.run decodes the output as UTF-8, a UnicodeDecodeError is raised in the reader thread, causing result.stdout to become None. This produces two cascading failures:

  1. UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 in position 8177 in the subprocess reader thread
  2. AttributeError: 'NoneType' object has no attribute 'split' in _scan_gateway_pids

Fix

  • Pass encoding='utf-8' and errors='ignore' explicitly to subprocess.run so undecodable bytes are silently skipped rather than raising
  • Add a None guard on result.stdout before calling .split() so the function returns an empty list cleanly instead of crashing

Testing

  • Syntax validation: python3 -m py_compile hermes_cli/gateway.py passes
  • No existing test coverage for Windows wmic path — the fix is defensive and non-breaking (adding encoding/errors to subprocess.run with non-Windows platforms has no effect; the None guard is a safe idempotent check)

Closes #17049.

Changed files

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

PR #17271: fix(gateway): add errors='replace' to subprocess.run for Windows wmic compatibility

Description (problem / solution / changelog)

Summary

Fixes #17049

On Windows with non-UTF-8 locale (e.g. Chinese/CJK), the wmic command outputs text in the system's ANSI codepage, which may contain bytes that are invalid UTF-8. When subprocess.run is called with text=True (which defaults to encoding='utf-8', errors='strict'), this causes a UnicodeDecodeError in the subprocess reader thread, and subsequently an AttributeError when result.stdout becomes None.

Changes

In _scan_gateway_pids() (hermes_cli/gateway.py):

  1. Windows wmic call: Replace text=True with encoding="utf-8", errors="replace" so that non-UTF-8 bytes are replaced with U+FFFD instead of raising UnicodeDecodeError
  2. Unix ps call: Same change for consistency and defensive robustness
  3. None guard: Add or result.stdout is None check before accessing result.stdout.split(), preventing AttributeError if decode fails despite errors='replace'

Test plan

  • Verified the fix targets the exact lines mentioned in the stack trace (#17049)
  • Manual test on Windows with CJK locale would confirm the fix
  • Existing _scan_gateway_pids tests continue to pass

Before (broken)

result = subprocess.run(
    ["wmic", "process", "get", "ProcessId,CommandLine", "/FORMAT:LIST"],
    capture_output=True,
    text=True,  # ← raises UnicodeDecodeError on non-UTF-8 wmic output
    timeout=10,
)
if result.returncode != 0:  # ← doesn't guard against None stdout
    return []

After (fixed)

result = subprocess.run(
    ["wmic", "process", "get", "ProcessId,CommandLine", "/FORMAT:LIST"],
    capture_output=True,
    encoding="utf-8",
    errors="replace",  # ← replaces invalid bytes instead of crashing
    timeout=10,
)
if result.returncode != 0 or result.stdout is None:  # ← defensive guard
    return []

Changed files

  • hermes_cli/gateway.py (modified, +576/-161)

Code Example

Report       https://paste.rs/3LZ59
agent.log    https://paste.rs/uAhOd
gateway.log  https://paste.rs/RmnLg

---



---

if is_windows():
    result = subprocess.run(
        ["wmic", "process", "get", "ProcessId,CommandLine", "/FORMAT:LIST"],
        capture_output=True,
        text=True,  # ← Implicitly uses UTF-8 encoding
        timeout=10,
    )
    if result.returncode != 0:
        return []
    current_cmd = ""
    for line in result.stdout.split("\n"):  # ← stdout is None after decode error

---

if is_windows():
    result = subprocess.run(
        ["wmic", "process", "get", "ProcessId,CommandLine", "/FORMAT:LIST"],
        capture_output=True,
        text=True,
        encoding='utf-8',  # Explicitly specify
        errors='ignore',   # ← Ignore undecodable bytes instead of crashing
        timeout=10,
    )
    if result.returncode != 0 or result.stdout is None:
        return []
    current_cmd = ""
    for line in result.stdout.split("\n"):
RAW_BUFFERClick to expand / collapse

Bug Description

Summary

Running hermes setup on Windows fails with two related errors:

  1. UnicodeDecodeError in the subprocess reader thread due to non-UTF-8 encoded wmic output
  2. AttributeError when trying to access result.stdout (which becomes None after the decode error)

Error Messages

Primary Error:

  • UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 in position 8177: invalid continuation byte File "C:\Python311\Lib\subprocess.py", line 1597, in _readerthread self._out.write(b''.join(res)) File "<frozen codecs>", line 322, in decode

Secondary Error (consequence of the first):

  • AttributeError: 'NoneType' object has no attribute 'split' File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\gateway.py", line 290, in _scan_gateway_pids for line in result.stdout.split("\n"):

Stack Trace

Exception in thread Thread-1 (_readerthread): Traceback (most recent call last): File "C:\Python311\Lib\threading.py", line 1038, in _bootstrap_inner self.run() File "C:\Python311\Lib\threading.py", line 975, in run self._target(*self._args, **self._kwargs) File "C:\Python311\Lib\subprocess.py", line 1597, in _readerthread self._out.write(b''.join(res)) File "<frozen codecs>", line 322, in decode UnicodeDecodeError: 'utf-8' codec can't decode byte 0xd0 in position 8177: invalid continuation byte

Traceback (most recent call last): File "<frozen runpy>", line 198, in _run_module_as_main File "<frozen runpy>", line 88, in _run_code File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\main.py", line 10160, in main args.func(args) File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\main.py", line 1522, in cmd_setup run_setup_wizard(args) File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\setup.py", line 3080, in run_setup_wizard _run_first_time_quick_setup(config, hermes_home, is_existing) File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\setup.py", line 3182, in _run_first_time_quick_setup setup_gateway(config) File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\setup.py", line 2405, in setup_gateway service_running = _is_service_running() File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\gateway.py", line 3186, in _is_service_running return len(find_gateway_pids()) > 0 File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\gateway.py", line 370, in find_gateway_pids for pid in _scan_gateway_pids(_exclude, all_profiles=all_profiles): File "C:\Users\feng7\AppData\Local\hermes\hermes-agent\hermes_cli\gateway.py", line 290, in _scan_gateway_pids for line in result.stdout.split("\n"): AttributeError: 'NoneType' object has no attribute 'split'

Steps to Reproduce

  1. Run hermes setup on a Windows system (particularly with non-English system locale)
  2. During the gateway service detection phase, the error occurs

Expected Behavior

The function should:

  • Decode wmic output using the system's code page (or handle encoding errors gracefully)
  • Successfully extract process IDs and command lines
  • Allow the setup wizard to continue

Actual Behavior

The function crashes with UnicodeDecodeError in the subprocess reader thread, then AttributeError when trying to access result.stdout.

Affected Component

Setup / Installation

Messaging Platform (if gateway-related)

No response

Debug Report

Report       https://paste.rs/3LZ59
agent.log    https://paste.rs/uAhOd
gateway.log  https://paste.rs/RmnLg

Operating System

WIndows 10

Python Version

3.11.5

Hermes Version

0.11.0 (2026.4.23)

Additional Logs / Traceback (optional)

Root Cause Analysis (optional)

Root Cause

The _scan_gateway_pids() function in hermes_cli/gateway.py (lines 278-290) executes the Windows wmic command with text=True and encoding='utf-8' (implicit), but:

  1. wmic output is not UTF-8: On Windows systems, especially with non-English locales, wmic outputs text in the system's code page (e.g., cp936 for Chinese, cp1252 for Western European), NOT UTF-8.

  2. UnicodeDecodeError in subprocess: When Python tries to decode wmic's output as UTF-8, it fails if the output contains non-UTF-8 bytes (like 0xd0 at position 8177), causing the reader thread to crash.

  3. Cascading failure: After the decode error, result.stdout becomes None, leading to the AttributeError.

Current problematic code (lines 278-290):

if is_windows():
    result = subprocess.run(
        ["wmic", "process", "get", "ProcessId,CommandLine", "/FORMAT:LIST"],
        capture_output=True,
        text=True,  # ← Implicitly uses UTF-8 encoding
        timeout=10,
    )
    if result.returncode != 0:
        return []
    current_cmd = ""
    for line in result.stdout.split("\n"):  # ← stdout is None after decode error

Proposed Fix (optional)

Use system encoding

if is_windows():
    result = subprocess.run(
        ["wmic", "process", "get", "ProcessId,CommandLine", "/FORMAT:LIST"],
        capture_output=True,
        text=True,
        encoding='utf-8',  # Explicitly specify
        errors='ignore',   # ← Ignore undecodable bytes instead of crashing
        timeout=10,
    )
    if result.returncode != 0 or result.stdout is None:
        return []
    current_cmd = ""
    for line in result.stdout.split("\n"):

Are you willing to submit a PR for this?

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

extent analysis

TL;DR

The most likely fix is to use the system's encoding when running the wmic command and ignore undecodable bytes to prevent the UnicodeDecodeError.

Guidance

  1. Specify the system encoding: When running the wmic command, use the encoding parameter of subprocess.run to specify the system's encoding instead of relying on the default UTF-8.
  2. Ignore undecodable bytes: Set the errors parameter to 'ignore' to prevent the UnicodeDecodeError from crashing the program.
  3. Check for None stdout: After running the command, check if result.stdout is None before trying to access it to prevent the AttributeError.
  4. Test with different locales: Test the fix with different system locales to ensure it works correctly in all cases.

Example

if is_windows():
    result = subprocess.run(
        ["wmic", "process", "get", "ProcessId,CommandLine", "/FORMAT:LIST"],
        capture_output=True,
        text=True,
        encoding='utf-8',  # Explicitly specify
        errors='ignore',   # Ignore undecodable bytes instead of crashing
        timeout=10,
    )
    if result.returncode != 0 or result.stdout is None:
        return []
    current_cmd = ""
    for line in result.stdout.split("\n"):

Notes

This fix assumes that ignoring undecodable bytes is acceptable for the specific use case. If the undecodable bytes are important, a different approach may be needed.

Recommendation

Apply the workaround by specifying the system encoding and ignoring undecodable bytes, as it is a simple and effective solution to the problem.

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