NousResearch/hermes-agent · error · Error

File uploads are not supported against OAuth-gated remote ba

Error message

File uploads are not supported against OAuth-gated remote backends yet.

What it means

The desktop REST bridge supports three auth modes; for authMode 'oauth' it rides Electron's net stack with JSON headers bound to the OAuth session partition, and multipart file upload bodies are not implemented on that path. When a request carries request.upload against an OAuth-gated remote backend, it throws this explicit error instead of silently corrupting the upload. It is a known capability gap, deliberately failing loudly.

Source

Thrown at apps/desktop/electron/main.ts:10879

  const timeoutMs = resolveTimeoutMs(request?.timeoutMs, DEFAULT_FETCH_TIMEOUT_MS)

  const requestPath = pathWithGlobalRemoteProfile(request.path, profile, profileRouteOptions(profile))

  const url = `${connection.baseUrl}${requestPath}`

  // OAuth gateways authenticate REST via EITHER a native bearer token
  // (cookieless RFC 8252 flow) OR the HttpOnly session cookie held in the OAuth
  // partition. Prefer the native bearer when present (mirroring
  // mintGatewayWsTicket): the native flow never sets a cookie, so routing an
  // oauth-mode REST call through the cookie-only path returns 401 no_cookie even
  // though a valid bearer is held. Cookie mode rides Electron's net stack bound
  // to the OAuth partition so the cookie attaches automatically. Token/local
  // modes keep using the static session-token header.
  if (connection.authMode === 'oauth') {
    // The OAuth path rides electron.net with JSON headers; multipart isn't
    // wired there. Fail loudly rather than corrupting the upload.
    if (request?.upload) {
      throw new Error('File uploads are not supported against OAuth-gated remote backends yet.')
    }

    // Native bearer first (cookieless). ensureNativeAccessToken transparently
    // refreshes a near-expiry AT via /auth/native/refresh; a null return means
    // no native session (resolveOauthRestAuth then selects the cookie path).
    const nativeAt = await ensureNativeAccessToken(connection.baseUrl).catch(() => null)
    const restAuth = resolveOauthRestAuth(nativeAt)

    if (restAuth.kind === 'bearer') {
      return fetchJson(url, null, {
        method: request?.method,
        body: request?.body,
        timeoutMs,
        bearer: restAuth.token
      })
    }

    return fetchJsonViaOauthSession(url, {

View on GitHub (pinned to c896c09c42)

Solutions

  1. Connect to that backend with a token (API token) instead of OAuth so uploads take the static-token fetch path
  2. Upload against a local backend or via the CLI/gateway directly, then reference the uploaded artifact
  3. If you own the code: implement multipart on the electron.net OAuth path (cookie or native bearer) — until then keep gating uploads on authMode !== 'oauth'
  4. In renderer UI, disable/hide the attach button when connection.authMode === 'oauth' and show 'uploads unsupported on OAuth remotes'

Example fix

// before (renderer)
await ipc.invoke('hermes:api', { path: '/api/upload', upload: file })

// after
if (connection.authMode === 'oauth') throw new Error('Uploads unsupported on OAuth remote — connect with a token')
await ipc.invoke('hermes:api', { path: '/api/upload', upload: file })
Defensive patterns

Strategy: validation

Validate before calling

if (request?.upload && connection.authMode === 'oauth') {
  throw new Error('Upload not available on OAuth remote — connect with a token or use a local backend')
}

Type guard

function uploadSupported(connection: { authMode: string }): boolean {
  return connection.authMode === 'token' || connection.authMode === 'local'
}

Try / catch

try { await api(path, { upload }) } catch (e) { if (e instanceof Error && e.message.includes('not supported against OAuth-gated')) notify('Switch to a token connection to upload files') else throw e }

Prevention

When it happens

Trigger: Any renderer API call that sets request.upload (file attachment) while the active connection config has authMode 'oauth' — e.g. attaching a file to a chat message against a Hermes Cloud/OAuth remote backend.

Common situations: Users on OAuth-gated remote (cloud) backends trying the file-attach feature that works fine against token/local connections; code paths that assume the upload path is auth-mode-agnostic.

Related errors


AI-assisted analysis of NousResearch/hermes-agent@c896c09c42 (2026-08-14). Data as JSON: /api/errors/6b75a74b6d588e20. Report an issue: GitHub.