{"id":"2f7c7f6f99a2e233","repo":"sindresorhus/got","slug":"failed-to-parse-link-header-link","errorCode":null,"errorMessage":"Failed to parse Link header: ${link}","messagePattern":"Failed to parse Link header: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"source/core/parse-link-header.ts","lineNumber":89,"sourceCode":"\t\t}\n\n\t\tconst reference = trimmedUriReference.slice(1, -1);\n\t\tconst parameters: Record<string, string> = {};\n\n\t\tif (reference.includes('<') || reference.includes('>')) {\n\t\t\tthrow new Error(`Invalid format of the Link header reference: ${trimmedUriReference}`);\n\t\t}\n\n\t\tif (rawLinkParameters.length === 0) {\n\t\t\tthrow new Error(`Unexpected end of Link header parameters: ${rawLinkParameters.join(';')}`);\n\t\t}\n\n\t\tfor (const rawParameter of rawLinkParameters) {\n\t\t\tconst trimmedRawParameter = rawParameter.trim();\n\t\t\tconst center = trimmedRawParameter.indexOf('=');\n\n\t\t\tif (center === -1) {\n\t\t\t\tthrow new Error(`Failed to parse Link header: ${link}`);\n\t\t\t}\n\n\t\t\tconst name = trimmedRawParameter.slice(0, center).trim();\n\t\t\tconst value = trimmedRawParameter.slice(center + 1).trim();\n\n\t\t\tparameters[name] = value;\n\t\t}\n\n\t\tparsed.push({\n\t\t\treference,\n\t\t\tparameters,\n\t\t});\n\t}\n\n\treturn parsed;\n}\n","sourceCodeStart":71,"sourceCodeEnd":106,"githubUrl":"https://github.com/sindresorhus/got/blob/e3924aa1e53a6ca3eb93a43618ce532442a89b40/source/core/parse-link-header.ts#L71-L106","documentation":"parse-link-header.ts:89: each `;`-separated link parameter must be a `name=value` pair. If a parameter has no `=` (e.g. `</p>; relnext` or `</p>; rel`), `indexOf('=')` returns -1 and Got throws with the full original `link` header in the message for context.","triggerScenarios":"A `Link` header like `</page2>; rel=\"next\"; bogus` (last parameter has no `=`), or `</page2>; next` (bare token). Distinct from 47–49 (which validate structure of the reference); this validates parameter syntax.","commonSituations":"A server concatenating parameters with malformed separators; an extension parameter written as a bare token instead of `name=value`; hand-built test fixtures with typos; an upstream that appends a flag-like parameter.","solutions":["Ensure every parameter after the reference is `name=value` (quoted value if it contains special chars).","Inspect the raw header and fix the malformed parameter on the server.","If the upstream cannot be fixed, disable link-based pagination for that endpoint.","Add a server-side unit test that round-trips the Link header through an RFC 8288 parser."],"exampleFix":"// before: upstream sends  Link: </p2>; rel=\"next\"; bogus\n\n// after: upstream sends   Link: </p2>; rel=\"next\"; title=\"bogus\"","handlingStrategy":"validation","validationCode":"function paramsHaveEquals(item) {\n  return item.split(';').slice(1).every(p => p.includes('='));\n}\nconst ok = (response.headers.link ?? '').split(',').every(paramsHaveEquals);","typeGuard":"const linkParamsWellFormed = (s: string): boolean =>\n  s.split(';').slice(1).every(p => p.trim().includes('='));","tryCatchPattern":null,"preventionTips":["Build Link parameters as `name=value` pairs only.","Round-trip-test server Link headers through a parser.","Disable pagination for endpoints with non-RFC8288 link syntax.","Capture raw headers when diagnosing pagination failures."],"tags":["link-header","parsing","pagination","rfc-8288"],"analyzedSha":"e3924aa1e53a6ca3eb93a43618ce532442a89b40","analyzedAt":"2026-08-03T19:22:24.770Z","schemaVersion":2}