{"record":{"id":"3824bbe647830a33","repo":"remix-run/remix","slug":"basepath-must-be-a-string","errorCode":null,"errorMessage":"basePath must be a string","messagePattern":"basePath must be a string","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"packages/assets/src/lib/asset-server.ts","lineNumber":1139,"sourceCode":"    throw new TypeError('hmr must create an object')\n  }\n  if (!('url' in channel) || typeof channel.url !== 'string') {\n    throw new TypeError('hmr must create a channel with a string url')\n  }\n  if (!('close' in channel) || typeof channel.close !== 'function') {\n    throw new TypeError('hmr must create a channel with a close function')\n  }\n  if (!('onFileEvents' in channel) || typeof channel.onFileEvents !== 'function') {\n    throw new TypeError('hmr must create a channel with an onFileEvents function')\n  }\n  if (!('updateWatchedFiles' in channel) || typeof channel.updateWatchedFiles !== 'function') {\n    throw new TypeError('hmr must create a channel with an updateWatchedFiles function')\n  }\n}\n\nfunction normalizeBasePath(basePath: string): string {\n  if (typeof basePath !== 'string') {\n    throw new TypeError('basePath must be a string')\n  }\n\n  return normalizePathname(basePath || '/').replace(/\\/+$/, '') || '/'\n}\n\nfunction normalizeFingerprintOptions(options: {\n  fingerprint: AssetServerOptions['fingerprint']\n  watch: AssetServerOptions['watch']\n}):\n  | {\n      enabled: false\n      buildId?: string\n    }\n  | {\n      enabled: true\n      buildId: string\n    } {\n  if (!options.fingerprint) {","sourceCodeStart":1121,"sourceCodeEnd":1157,"githubUrl":"https://github.com/remix-run/remix/blob/9696913134be3a4423513d2775f7b31d6917c049/packages/assets/src/lib/asset-server.ts#L1121-L1157","documentation":"The asset server's `basePath` option must be a string (it is normalized and default-corrected to `/`). This error fires at option-normalization time when a non-string value such as `null`, a number, or `undefined` sneaks in from an env var or config file.","triggerScenarios":"Passing `basePath: undefined`/`null`/non-string to the asset server options, e.g. `basePath: process.env.BASE_PATH` when the env var is unset or parsed as a number.","commonSituations":"Reading `basePath` from an environment variable without a fallback; YAML/TOML configs coercing values; spreading a partial config where `basePath` was explicitly set to null.","solutions":["Default the value: `basePath: env.BASE_PATH ?? '/'`","If it comes from user config, validate/coerce to string before passing it to the asset server","Check for accidental `null` assignment in config merge/spread logic"],"exampleFix":"// before\nbasePath: process.env.ASSET_BASE_PATH\n// after\nbasePath: process.env.ASSET_BASE_PATH ?? '/'","handlingStrategy":"type-guard","validationCode":"let basePath: string = typeof rawBasePath === 'string' ? rawBasePath : '/'","typeGuard":"function isBasePath(v: unknown): v is string {\n  return typeof v === 'string'\n}","tryCatchPattern":null,"preventionTips":["Always default env-derived basePath with ?? '/'","Validate config objects at the edge (env/config load) rather than inside the server call"],"tags":["config","validation","asset-server","basepath"],"backgroundTag":"config-type-validation","analyzedSha":"9696913134be3a4423513d2775f7b31d6917c049","analyzedAt":"2026-08-27T19:55:01.024Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}