diff --git a/utils/apiFetch.ts b/utils/apiFetch.ts index b264491..2fc7b98 100644 --- a/utils/apiFetch.ts +++ b/utils/apiFetch.ts @@ -37,6 +37,18 @@ export async function apiFetch(options: ApiFetchOptions): Promise { headers["x-vercel-protection-bypass"] = bypassSecret; } + // never send Content-Type on body-less requests. empirically, Vercel's + // Next.js lambda adapter (Next 16.1.x) throws `SyntaxError: Unexpected + // end of data` before delegating to the route handler — returning a 500 — + // when Content-Type is set but no body is present. exact mechanism is + // unverified (minified runtime frame), but Content-Type on a body-less + // request has no defined semantics per RFC 9110 §8.3 anyway. see #692. + if (!options.body) { + for (const key of Object.keys(headers)) { + if (key.toLowerCase() === "content-type") delete headers[key]; + } + } + log.debug(`api fetch: ${options.method ?? "GET"} ${url.pathname}`); const init: RequestInit = { diff --git a/utils/runContext.ts b/utils/runContext.ts index 5c7f747..9235fb7 100644 --- a/utils/runContext.ts +++ b/utils/runContext.ts @@ -88,7 +88,6 @@ export async function fetchRunContext(params: { try { const headers: Record = { Authorization: `Bearer ${params.token}`, - "Content-Type": "application/json", }; if (params.oidcToken) { headers["X-GitHub-OIDC-Token"] = params.oidcToken;