Skip to content

fix(desktop): drop manual Content-Length in OAuth net.request (ERR_INVALID_ARGUMENT) - #40174

Closed
Kyzcreig wants to merge 1 commit into
NousResearch:mainfrom
ANG-Ventures:fix/desktop-oauth-content-length
Closed

fix(desktop): drop manual Content-Length in OAuth net.request (ERR_INVALID_ARGUMENT)#40174
Kyzcreig wants to merge 1 commit into
NousResearch:mainfrom
ANG-Ventures:fix/desktop-oauth-content-length

Conversation

@Kyzcreig

@Kyzcreig Kyzcreig commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Changing the model from the desktop app Settings → Models → Apply (and any other body-bearing POST) fails for remote-backend OAuth users with:

Error invoking remote method 'hermes:api': Error: net::ERR_INVALID_ARGUMENT

Root cause

fetchJsonViaOauthSession() in apps/desktop/electron/main.cjs manually sets Content-Length on the Electron net.request:

request.setHeader('Content-Type', 'application/json')
if (body) request.setHeader('Content-Length', String(body.length))

Electron's net.request (ClientRequest, Chromium net stack) treats Content-Length as a protected header it computes itself from request.write(body). Setting it explicitly throws net::ERR_INVALID_ARGUMENT, so the request fails before it ever leaves the app.

This only bit the OAuth/remote path (electronNet) on body-bearing POSTs (e.g. POST /api/model/set). GET and bodyless POSTs were unaffected, and the local/token path (fetchJson, Node http) tolerates a manual Content-Length — which is why it regressed only for remote-backend OAuth users. Introduced in #39921.

Empirical verification

Headless Electron net.request probe (Electron 40):

WITH Content-Length    -> net::ERR_INVALID_ARGUMENT   (matches the report)
WITHOUT Content-Length -> net::ERR_UNSAFE_PORT         (header validation passed; only the test port was rejected)

Fix

Remove the manual Content-Length header; let Electron compute it from request.write(body). The backend POST /api/model/set was verified to return 200 for the same payload, confirming the failure was entirely client-side.

…VALID_ARGUMENT)

Electron's net.request (ClientRequest, Chromium net stack) treats
Content-Length as a protected header it computes itself from
request.write(body). Setting it explicitly throws
net::ERR_INVALID_ARGUMENT and the request fails before leaving the app.

This only affected the OAuth/remote path (fetchJsonViaOauthSession via
electronNet) on body-bearing POSTs — most visibly POST /api/model/set
from Settings -> Models 'Apply', which surfaced as
"Error invoking remote method 'hermes:api': Error: net::ERR_INVALID_ARGUMENT".
GET and bodyless POSTs were unaffected, and the local/token path
(fetchJson via Node http) tolerates a manual Content-Length, so it
regressed only for remote-backend OAuth users.

Verified empirically with a headless Electron net.request probe:
  WITH Content-Length    -> net::ERR_INVALID_ARGUMENT
  WITHOUT Content-Length -> net::ERR_UNSAFE_PORT (header validation passed)

Introduced in NousResearch#39921.
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have area/auth Authentication, OAuth, credential pools labels Jun 6, 2026

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved. Drops manual Content-Length header in desktop OAuth net.request to fix ERR_INVALID_ARGUMENT.

@Kyzcreig

Copy link
Copy Markdown
Contributor Author

Closing as implemented on current main (7c14d2a046217c5ccbaa06a9449b0fcf329221f9). The OAuth Electron request path now lives in apps/desktop/electron/oauth-net-request.ts / oauth-session-request.test.ts: setJsonRequestHeaders sets only Content-Type, Chromium frames the serialized body, and no forbidden Content-Length is set. Current verification: npx tsx --test electron/oauth-net-request.test.ts electron/oauth-session-request.test.ts → 4 passed, 0 failed. Porting the old main.cjs hunk onto current main.ts would reintroduce obsolete structure.

@Kyzcreig Kyzcreig closed this Jul 12, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/auth Authentication, OAuth, credential pools P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants