coleam00/Archon · error

OpenAI token ${operation} returned a non-JSON response (HTTP

Error message

OpenAI token ${operation} returned a non-JSON response (HTTP ${response.status}).

What it means

postTokenRequest (openai-oauth.ts:211) throws when OpenAI's token endpoint responds HTTP 200 but the body is not valid JSON — for example an HTML proxy/maintenance/captive-portal page. The flow labels the condition clearly instead of letting response.json() throw a raw SyntaxError that would be mistaken for an Archon bug.

Source

Thrown at packages/core/src/credentials/openai-oauth.ts:211

        errorCode = parsed.error;
      } else if (parsed.error && typeof parsed.error === 'object') {
        const code = (parsed.error as { code?: unknown }).code;
        if (typeof code === 'string') errorCode = code;
      }
    } catch {
      // Non-JSON error body — drop it entirely; the status code must suffice.
    }
    throw new Error(
      `OpenAI token ${operation} failed (${response.status})${errorCode ? `: ${errorCode}` : ''}`
    );
  }
  let raw: unknown;
  try {
    raw = await response.json();
  } catch {
    // An HTTP 200 with a non-JSON body (proxy/maintenance page) must surface
    // as a labeled error, not a raw SyntaxError mistaken for an Archon bug.
    throw new Error(
      `OpenAI token ${operation} returned a non-JSON response (HTTP ${response.status}).`
    );
  }
  return raw as OpenAiTokenResponse;
}

/**
 * Map a token response onto the stored credential blob. Fails loud on a
 * missing `id_token` at exchange time (the whole point of owning this flow);
 * on refresh, a response that omits `id_token`/`refresh_token` PRESERVES the
 * previous values instead of degrading the blob.
 */
function credentialsFromTokenResponse(
  json: OpenAiTokenResponse,
  operation: 'exchange' | 'refresh',
  previous?: OAuthCredentials
): OpenAiOAuthCredentials {
  const access = typeof json.access_token === 'string' ? json.access_token : '';

View on GitHub (pinned to 0773b97458)

Solutions

  1. Check what your proxy/network returns for the token endpoint (curl -i the URL) and fix interception/allowlisting.
  2. Move the host to a network without captive portals or HTML-rewriting middleboxes.
  3. Disable or reconfigure TLS-intercepting proxies that inject HTML bodies.
  4. Retry from a clean network; the error is environment-caused, not code-caused.
Defensive patterns

Strategy: fallback

Validate before calling

// Probe that the token endpoint returns JSON, not an intercepting HTML page
const probe = await fetch('https://auth.openai.com/.well-known/openid-configuration').catch(() => null);
const ct = probe?.headers.get('content-type') ?? '';
if (!ct.includes('application/json')) {
  throw new Error('A proxy/captive portal is intercepting OpenAI traffic; fix the network first.');
}

Type guard

function isNonJsonResponseError(e: unknown): boolean {
  return e instanceof Error && /returned a non-JSON response \(HTTP \d+\)/.test(e.message);
}

Try / catch

try {
  await refreshToken(token);
} catch (e) {
  if (isNonJsonResponseError(e)) {
    // Environment problem (proxy/HTML body): surface network guidance, not a code bug
    reportNetworkIssue(e);
    return;
  }
  throw e;
}

Prevention

When it happens

Trigger: An HTTP 200 response from OPENAI_TOKEN_URL whose body fails JSON.parse — typically an intercepting corporate proxy, captive portal, maintenance page, or misrouted gateway returning HTML.

Common situations: Hotel/office captive portal intercepting HTTPS (with weak interception); corporate proxy returning an HTML block page with status 200; a misconfigured local gateway or API-mocking tool returning plain text.

Related errors


AI-assisted analysis of coleam00/Archon@0773b97458 (2026-09-01). Data as JSON: /api/errors/6bffe577abbb75ed. Report an issue: GitHub.