{"id":"bf55abd2964f559f","repo":"sindresorhus/got","slug":"failed-to-parse-link-header-value","errorCode":null,"errorMessage":"Failed to parse Link header: ${value}","messagePattern":"Failed to parse Link header: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"source/core/parse-link-header.ts","lineNumber":51,"sourceCode":"\t\tif (!inQuotes && character === '>') {\n\t\t\tinReference = false;\n\t\t\tcurrent += character;\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Link headers use both quoted strings and <URI-reference> values, so raw\n\t\t// splitting on `,` / `;` would break valid values containing those characters.\n\t\tif (!inQuotes && !inReference && character === separator) {\n\t\t\tvalues.push(current);\n\t\t\tcurrent = '';\n\t\t\tcontinue;\n\t\t}\n\n\t\tcurrent += character;\n\t}\n\n\tif (inQuotes || isEscaped) {\n\t\tthrow new Error(`Failed to parse Link header: ${value}`);\n\t}\n\n\tvalues.push(current);\n\treturn values;\n};\n\nexport default function parseLinkHeader(link: string) {\n\tconst parsed = [];\n\n\tconst items = splitHeaderValue(link, ',');\n\n\tfor (const item of items) {\n\t\t// https://tools.ietf.org/html/rfc5988#section-5\n\t\tconst [rawUriReference, ...rawLinkParameters] = splitHeaderValue(item, ';') as [string, ...string[]];\n\t\tconst trimmedUriReference = rawUriReference.trim();\n\n\t\t// eslint-disable-next-line @typescript-eslint/prefer-string-starts-ends-with\n\t\tif (trimmedUriReference[0] !== '<' || trimmedUriReference.at(-1) !== '>') {","sourceCodeStart":33,"sourceCodeEnd":69,"githubUrl":"https://github.com/sindresorhus/got/blob/e3924aa1e53a6ca3eb93a43618ce532442a89b40/source/core/parse-link-header.ts#L33-L69","documentation":"From `splitHeaderValue` in parse-link-header.ts:51. Got walks the Link header character-by-character tracking quote/escape state; if the input ends with an open quote or a dangling backslash escape, the parser considers the header malformed and throws. This guards the Link-pagination feature (`pagination.paginate` returning a `link` header) against feeding garbage into `URL`.","triggerScenarios":"A server returns a `Link` header with an unterminated quoted value (e.g. `</page2>; rel=\"next`, missing closing quote) or a trailing backslash. Got attempts to parse it for pagination and throws at line 51.","commonSituations":"Misbehaving/legacy upstream proxies that truncate headers; a CDN rewriting headers and mangling quotes; an origin returning a hand-built Link header with a typo; enabling `pagination` against an endpoint whose `Link` is non-RFC8288 compliant.","solutions":["Inspect the raw `Link` header from the failing response (curl -i or `response.headers.link`) and report it to the upstream maintainer.","If you control the server, ensure all quoted parameter values are closed and escapes are paired.","Disable Got's automatic link parsing (`pagination` off) if the endpoint is known-broken and you don't need cursor walking.","Pre-sanitize the header before passing to a manual Link parser if you must tolerate malformed upstreams."],"exampleFix":"// before: upstream sends  Link: </p2>; rel=\"next\n// (unterminated quote)\n\n// after: fix the server to send  Link: </p2>; rel=\"next\"","handlingStrategy":"try-catch","validationCode":"function looksBalanced(header) {\n  let quotes = 0, escaped = false;\n  for (const ch of header) {\n    if (escaped) { escaped = false; continue; }\n    if (ch === '\\\\') { escaped = true; continue; }\n    if (ch === '\"') quotes++;\n  }\n  return !escaped && quotes % 2 === 0;\n}\nif (!looksBalanced(response.headers.link ?? '')) {\n  // skip pagination\n}","typeGuard":null,"tryCatchPattern":"try {\n  for await (const page of got.paginate(url)) { /* ... */ }\n} catch (error) {\n  if (error.message.startsWith('Failed to parse Link header')) {\n    // upstream sent a malformed Link header; fall back to manual paging\n  } else throw error;\n}","preventionTips":["Sanity-check the `Link` header before enabling pagination against an unknown endpoint.","Report malformed headers upstream and pin pagination to known-good endpoints.","Add a regression test using a captured raw header from the real upstream.","Log `response.headers.link` when pagination fails to aid diagnosis."],"tags":["link-header","parsing","pagination"],"analyzedSha":"e3924aa1e53a6ca3eb93a43618ce532442a89b40","analyzedAt":"2026-08-03T19:22:24.770Z","schemaVersion":2}