hermes - 💡(How to fix) Fix Desktop (remote gateway, OAuth mode): saving settings fails with net::ERR_INVALID_ARGUMENT — manual Content-Length on Electron net.request

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…

In the desktop app connected to a remote gateway with authMode=oauth, saving any setting fails with the toast "Autosave failed — net::ERR_INVALID_ARGUMENT" and the value reverts. Reads work fine (the app shows "Gateway ready"); only body-bearing writes (PUT/POST) fail.

Root Cause

apps/desktop/electron/main.cjsfetchJsonViaOauthSession() is the only request path that uses Electron's net module (needed for the OAuth session-cookie partition). For body-bearing requests it sets the Content-Length header manually:

request.setHeader('Content-Length', String(body.length))

Since Electron 7+, manually setting Content-Length (or Host) on a net.request throws net::ERR_INVALID_ARGUMENT — the net module computes Content-Length itself. See electron/electron#21091 and electron/electron#21577.

Because the header is only set when there's a body (if (body)), GET reads skip it and work, while PUT/POST writes (saveHermesConfig PUT /api/config, setEnvVar, etc.) fail. The Node https.request path (fetchJson) is unaffected — a manual Content-Length is valid there — which is why token / local mode works and only OAuth remote mode is broken.

Appears to have been introduced by commit 9d07927a2 ("desktop: OAuth-aware remote gateway connection").

Fix Action

Fix

Remove the manual Content-Length header in fetchJsonViaOauthSession and let Electron compute it:

-      request.setHeader('Content-Length', String(body.length))

(Leave the Node-path fetchJson Content-Length handling as-is.) Verified locally: removing that single line and repackaging the asar restores settings-save in OAuth remote mode, with no regression to token/local mode.

Workaround

Use token auth for the remote gateway (uses the unaffected Node https path), or patch the line above and rebuild the desktop app.

Code Example

request.setHeader('Content-Length', String(body.length))

---

-      request.setHeader('Content-Length', String(body.length))
RAW_BUFFERClick to expand / collapse

Summary

In the desktop app connected to a remote gateway with authMode=oauth, saving any setting fails with the toast "Autosave failed — net::ERR_INVALID_ARGUMENT" and the value reverts. Reads work fine (the app shows "Gateway ready"); only body-bearing writes (PUT/POST) fail.

Environment

  • hermes-agent v2026.5.29-866-g1a3e60852
  • Electron 40.9.3
  • Desktop remote gateway + authMode=oauth
  • Backend reached over HTTPS via a reverse proxy

Steps to reproduce

  1. Connect the desktop app to a remote gateway using OAuth auth mode.
  2. Change any setting (e.g. anything that PUTs /api/config, or setEnvVar).
  3. Toast: Autosave failed — net::ERR_INVALID_ARGUMENT; the setting reverts.

GET-based reads (config load, status) succeed, so the gateway shows as ready — only writes fail.

Root cause

apps/desktop/electron/main.cjsfetchJsonViaOauthSession() is the only request path that uses Electron's net module (needed for the OAuth session-cookie partition). For body-bearing requests it sets the Content-Length header manually:

request.setHeader('Content-Length', String(body.length))

Since Electron 7+, manually setting Content-Length (or Host) on a net.request throws net::ERR_INVALID_ARGUMENT — the net module computes Content-Length itself. See electron/electron#21091 and electron/electron#21577.

Because the header is only set when there's a body (if (body)), GET reads skip it and work, while PUT/POST writes (saveHermesConfig PUT /api/config, setEnvVar, etc.) fail. The Node https.request path (fetchJson) is unaffected — a manual Content-Length is valid there — which is why token / local mode works and only OAuth remote mode is broken.

Appears to have been introduced by commit 9d07927a2 ("desktop: OAuth-aware remote gateway connection").

Fix

Remove the manual Content-Length header in fetchJsonViaOauthSession and let Electron compute it:

-      request.setHeader('Content-Length', String(body.length))

(Leave the Node-path fetchJson Content-Length handling as-is.) Verified locally: removing that single line and repackaging the asar restores settings-save in OAuth remote mode, with no regression to token/local mode.

Workaround

Use token auth for the remote gateway (uses the unaffected Node https path), or patch the line above and rebuild the desktop app.

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