{"record":{"id":"45ebd8357b7364a0","repo":"GitbookIO/gitbook","slug":"oauth-server-endpoint-responded-with-response","errorCode":null,"errorMessage":"OAuth server ${endpoint} responded with ${response.status}","messagePattern":"OAuth server (.+?) responded with (.+?)","errorType":"exception","errorClass":"SiteOAuthConsentError","httpStatus":null,"severity":"error","filePath":"packages/gitbook/src/lib/site-oauth/index.ts","lineNumber":122,"sourceCode":"    const signature = createHmac('sha256', GITBOOK_SITE_OAUTH_SIGNING_SECRET)\n        .update(`${siteId}:${timestamp}:${rawBody}`)\n        .digest('hex');\n\n    const url = new URL(GITBOOK_OAUTH_SERVER_URL);\n    url.pathname += `/${encodeURIComponent(siteId)}/${endpoint}`;\n    const response = await fetch(url, {\n        method: 'POST',\n        headers: {\n            'content-type': 'application/json',\n            'x-gitbook-signature': signature,\n            'x-gitbook-timestamp': String(timestamp),\n        },\n        body: rawBody,\n        cache: 'no-store',\n    });\n\n    if (!response.ok) {\n        throw new SiteOAuthConsentError(\n            `OAuth server ${endpoint} responded with ${response.status}`,\n            response.status\n        );\n    }\n\n    return (await response.json()) as T;\n}\n","sourceCodeStart":104,"sourceCodeEnd":130,"githubUrl":"https://github.com/GitbookIO/gitbook/blob/db67585ee243d063c459a855988f21612cea9c95/packages/gitbook/src/lib/site-oauth/index.ts#L104-L130","documentation":"postToConsentEndpoint throws SiteOAuthConsentError with the upstream HTTP status when the external OAuth consent server answers a non-2xx. The message names the endpoint and the status, distinguishing transport-level rejection (this error) from later consent-decision failures.","triggerScenarios":"startSiteOAuthConsent or submitSiteOAuthConsentDecision posting to the configured OAuth consent endpoint and receiving 4xx/5xx — wrong client_id/redirect_uri (400/401), expired/invalid consent token (410/401), consent server outage (5xx), or an endpoint URL misconfigured in site OAuth settings.","commonSituations":"OAuth provider config drift (redirect URI not registered, client credentials rotated), consent tokens expiring while the user sits on the form, the consent service being down or rate-limiting, or a typo in the endpoint URL stored in the integration config.","solutions":["Read the status in the message: 4xx → fix the OAuth client config (client_id, secret, redirect URIs) at the provider; 5xx → check the consent service health and retry","Verify the consent endpoint URL in your site OAuth configuration is current and reachable from the deployment","Re-initiate the consent flow so a fresh consent token is used if the old one expired","Capture the response body from the provider (add temporary logging) — the status alone rarely pinpoints the field at fault"],"exampleFix":"// before\nconst result = await startSiteOAuthConsent(config);\n\n// after\ntry {\n    const result = await startSiteOAuthConsent(config);\n} catch (e) {\n    if (e instanceof SiteOAuthConsentError && e.status >= 500) {\n        return retryableErrorPage(e);\n    }\n    throw e;\n}","handlingStrategy":"try-catch","validationCode":"// Pre-flight the consent endpoint before starting the flow\nconst ping = await fetch(endpoint, { method: 'OPTIONS' });\nif (!ping.ok) throw new Error(`Consent endpoint unreachable (${ping.status})`);","typeGuard":"function isConsentEndpointError(e: unknown): e is SiteOAuthConsentError {\n    return e instanceof SiteOAuthConsentError && /OAuth server .* responded with/.test(e.message);\n}","tryCatchPattern":"try {\n    await startSiteOAuthConsent(config);\n} catch (e) {\n    if (isConsentEndpointError(e)) {\n        if (e.status >= 500 || e.status === 429) return retryWithBackoff();\n        return renderOAuthConfigError(e);\n    }\n    throw e;\n}","preventionTips":["Keep OAuth client_id/secret/redirect URIs in sync with the provider after any rotation","Log the upstream response body (not just status) when consent calls fail","Retry only 5xx/429; persistent 4xx means configuration drift"],"tags":["oauth","consent","upstream","http-status"],"backgroundTag":"oauth-provider-request-failed","analyzedSha":"db67585ee243d063c459a855988f21612cea9c95","analyzedAt":"2026-08-28T17:49:47.831Z","schemaVersion":2},"datasetVersion":"2026-08-28T21:17:43.275Z"}