{"record":{"id":"3254c4bfe863192d","repo":"vitejs/vite","slug":"the-value-passed-to-base-option-was-malformed-i","errorCode":null,"errorMessage":"The value passed to \"base\" option was malformed. It should be a valid URL.","messagePattern":"The value passed to \"base\" option was malformed\\. It should be a valid URL\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/vite/src/node/config.ts","lineNumber":2340,"sourceCode":"  }\n\n  // parse base when command is serve or base is not External URL\n  if (!isBuild || !isExternal) {\n    base = new URL(base, 'http://vite.dev').pathname\n    // ensure leading slash\n    if (base[0] !== '/') {\n      base = '/' + base\n    }\n  }\n\n  return base\n}\n\nfunction decodeBase(base: string): string {\n  try {\n    return decodeURI(base)\n  } catch {\n    throw new Error(\n      'The value passed to \"base\" option was malformed. It should be a valid URL.',\n    )\n  }\n}\n\nexport function sortUserPlugins(\n  plugins: (Plugin | Plugin[])[] | undefined,\n): [Plugin[], Plugin[], Plugin[]] {\n  const prePlugins: Plugin[] = []\n  const postPlugins: Plugin[] = []\n  const normalPlugins: Plugin[] = []\n\n  if (plugins) {\n    plugins.flat().forEach((p) => {\n      if (p.enforce === 'pre') prePlugins.push(p)\n      else if (p.enforce === 'post') postPlugins.push(p)\n      else normalPlugins.push(p)\n    })","sourceCodeStart":2322,"sourceCodeEnd":2358,"githubUrl":"https://github.com/vitejs/vite/blob/b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab/packages/vite/src/node/config.ts#L2322-L2358","documentation":"Vite calls decodeBase to URI-decode the resolved base path so encoded characters (e.g. %20) work in URLs. If base contains a malformed percent sequence, decodeURI throws and Vite re-wraps it as 'base option was malformed'. The check assumes base already passed URL parsing upstream; only the decode step can fail.","triggerScenarios":"Setting config.base to a string containing an invalid percent escape, e.g. '%%', '%zz', or a stray '%' followed by non-hex characters.","commonSituations":"Dynamic base computation that concatenates a percent-encoded segment incorrectly; copy-pasting a URL with a broken fragment; build scripts that template base from env vars containing stray %.","solutions":["Correct the percent-encoding in base (use %20 for space, %2F for slash, etc.).","Avoid raw '%' in base; if a literal percent is needed, encode it as %25.","If base is computed, validate it with new URL(...) before passing to Vite."],"exampleFix":"// before\nexport default defineConfig({ base: '/my%path%' })\n// after\nexport default defineConfig({ base: '/my%25path%25' }) // literal percent signs","handlingStrategy":"validation","validationCode":"function isValidBase(base) {\n  try { decodeURI(base); new URL(base, 'http://vite.dev'); return true; } catch { return false; }\n}","typeGuard":"function isDecodableBase(base) {\n  try { decodeURI(base); return true; } catch { return false; }\n}","tryCatchPattern":null,"preventionTips":["Validate base with new URL(...) before passing it in.","Encode literal percent signs as %25."],"tags":["config","base","url"],"backgroundTag":null,"analyzedSha":"b4d66fee14d970f45b8a6f3d7d6aee73ca9b88ab","analyzedAt":"2026-08-11T11:49:19.515Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-23T08:17:48.524Z"}