{"record":{"id":"4c74be91ff5efc3b","repo":"facebook/docusaurus","slug":"url-must-be-a-string-received-typeof-component","errorCode":null,"errorMessage":"Url must be a string. Received ${typeof component}","messagePattern":"Url must be a string\\. Received (.+?)","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/docusaurus-utils/src/urlUtils.ts","lineNumber":57,"sourceCode":"    if (first.startsWith('file:') && urls[0].startsWith('/')) {\n      // Force a double slash here, else we lose the information that the next\n      // segment is an absolute path\n      urls[0] = `${first}//${urls[0]}`;\n    } else {\n      urls[0] = first + urls[0];\n    }\n  }\n\n  // There must be two or three slashes in the file protocol,\n  // two slashes in anything else.\n  const replacement = urls[0].match(/^file:\\/\\/\\//) ? '$1:///' : '$1://';\n  urls[0] = urls[0].replace(/^(?<protocol>[^/:]+):\\/*/, replacement);\n\n  for (let i = 0; i < urls.length; i += 1) {\n    let component = urls[i];\n\n    if (typeof component !== 'string') {\n      throw new TypeError(`Url must be a string. Received ${typeof component}`);\n    }\n\n    if (component === '') {\n      if (i === urls.length - 1 && hasEndingSlash) {\n        resultArray.push('/');\n      }\n      continue;\n    }\n\n    if (component !== '/') {\n      if (i > 0) {\n        // Removing the starting slashes for each component but the first.\n        component = component.replace(\n          /^\\/+/,\n          // Special case where the first element of rawUrls is empty\n          // [\"\", \"/hello\"] => /hello\n          component.startsWith('/') && !hasStartingSlash ? '/' : '',\n        );","sourceCodeStart":39,"sourceCodeEnd":75,"githubUrl":"https://github.com/facebook/docusaurus/blob/3f483e80e326cc646b54b83d564b3f0c4881b9a6/packages/docusaurus-utils/src/urlUtils.ts#L39-L75","documentation":"Thrown by normalizeUrl() inside the per-segment loop when an element of the input array is not a string. normalizeUrl is a URL-join utility that walks each segment assuming it is a string; a non-string element (number, undefined, null, object) is a type error in the caller. The error reports the typeof of the offending segment.","triggerScenarios":"Calling normalizeUrl([...segments]) where at least one segment is not a string — e.g. a variable that evaluated to undefined, a number accidentally included, or an object produced by a buggy expression. The check is reached for every segment after the protocol-normalization step, so even segments beyond the first are type-checked.","commonSituations":"Building a URL from config values where one optional field was undefined. Spread of an array that contains nulls. A locale or version variable that is a number rather than a string. Calling normalizeUrl on a value that came from JSON where the field was absent.","solutions":["Inspect the error's typeof hint and trace which segment of the input array matches that type.","Coerce or default every segment to a string before calling normalizeUrl (e.g. `segment ?? ''` or String(segment)).","Filter out non-string segments upstream with arr.filter((s): s is string => typeof s === 'string') if empty/missing segments should be dropped.","Add a runtime assertion at the boundary where the array is assembled so the bug surfaces at its source."],"exampleFix":"// before\nnormalizeUrl([baseUrl, maybeUndefinedVersion, slug]);\n\n// after\nnormalizeUrl([baseUrl, version ?? '', slug].filter(Boolean));","handlingStrategy":"type-guard","validationCode":"function allStrings(segments: unknown[]): segments is string[] {\n  return segments.every(s => typeof s === 'string');\n}\n\nif (!allStrings(rawUrls)) {\n  rawUrls = rawUrls.filter((s): s is string => typeof s === 'string');\n}\nnormalizeUrl(rawUrls);","typeGuard":"function isStringArray(arr: unknown): arr is string[] {\n  return Array.isArray(arr) && arr.every(s => typeof s === 'string');\n}","tryCatchPattern":"try {\n  normalizeUrl(rawUrls);\n} catch (err) {\n  if (err instanceof TypeError && err.message.startsWith('Url must be a string')) {\n    // a non-string segment slipped in; filter and retry\n  }\n  throw err;\n}","preventionTips":["Type the segments array as string[] at every boundary so non-strings are caught at compile time.","Filter or default optional segments (version ?? '') before assembling the array.","Validate config-sourced URL pieces with a typeof check before passing them to normalizeUrl."],"tags":["url","type-error","validation","type-guard"],"backgroundTag":null,"analyzedSha":"3f483e80e326cc646b54b83d564b3f0c4881b9a6","analyzedAt":"2026-08-12T13:25:04.382Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}