{"record":{"id":"cf1b042aff9dff3e","repo":"sveltejs/kit","slug":"keypath-option-must-be-an-absolute-path-if-spe","errorCode":null,"errorMessage":"${keypath} option must be an absolute path, if specified. See https://svelte.dev/docs/kit/configuration#paths","messagePattern":"(.+?) option must be an absolute path, if specified\\. See https://svelte\\.dev/docs/kit/configuration#paths","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/kit/src/core/config/options.js","lineNumber":203,"sourceCode":"\n\tpaths: object({\n\t\tbase: validate('', (input, keypath) => {\n\t\t\tassert_string(input, keypath);\n\n\t\t\tif (input !== '' && (input.endsWith('/') || !input.startsWith('/'))) {\n\t\t\t\tthrow new Error(\n\t\t\t\t\t`${keypath} option must either be the empty string or a root-relative path that starts but doesn't end with '/'. See https://svelte.dev/docs/kit/configuration#paths`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\treturn input;\n\t\t}),\n\t\tassets: validate('', (input, keypath) => {\n\t\t\tassert_string(input, keypath);\n\n\t\t\tif (input) {\n\t\t\t\tif (!/^[a-z]+:\\/\\//.test(input)) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${keypath} option must be an absolute path, if specified. See https://svelte.dev/docs/kit/configuration#paths`\n\t\t\t\t\t);\n\t\t\t\t}\n\n\t\t\t\tif (input.endsWith('/')) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\t`${keypath} option must not end with '/'. See https://svelte.dev/docs/kit/configuration#paths`\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn input;\n\t\t}),\n\t\torigin: validate(undefined, (input, keypath) => {\n\t\t\tassert_string(input, keypath);\n\n\t\t\tlet url;\n","sourceCodeStart":185,"sourceCodeEnd":221,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/kit/src/core/config/options.js#L185-L221","documentation":"`paths.assets` specifies where static assets are served from and, if set, must be an absolute URL (matching `/^[a-z]+:\\/\\//`, i.e. a scheme like `https://`). Relative paths or bare hostnames are rejected because asset URLs must resolve independently of `paths.base`.","triggerScenarios":"`paths.assets: 'cdn.example.com'` (no scheme), `paths.assets: '/static'` (relative path), or any value lacking a `scheme://` prefix.","commonSituations":"Using an external CDN and forgetting the `https://` prefix; assuming assets behaves like `base` (root-relative); typos like `http:/cdn...` with a single slash.","solutions":["Prefix the value with its scheme: `https://cdn.example.com`","Leave `assets` as `''` (default) to serve assets from the same origin — usually what you want","Validate with `new URL(value)` before assigning to confirm it parses"],"exampleFix":"// before\npaths: { assets: 'cdn.example.com' }\n// after\npaths: { assets: 'https://cdn.example.com' }","handlingStrategy":"validation","validationCode":"const assets = config.paths?.assets;\nif (assets && !/^[a-z]+:\\/\\//.test(assets)) {\n  throw new Error(`paths.assets must be an absolute URL with a scheme, got: ${assets}`);\n}","typeGuard":"function isAbsoluteAssetUrl(v) {\n  return v === undefined || v === '' || (typeof v === 'string' && /^[a-z]+:\\/\\//.test(v));\n}","tryCatchPattern":"try {\n  assertAssetsUrl(config.paths?.assets);\n} catch (e) {\n  if (String(e.message).includes('must be an absolute path, if specified')) {\n    console.error('Prefix assets with its scheme, e.g. https://cdn.example.com');\n  }\n  throw e;\n}","preventionTips":["Leave `assets` unset unless using a separate asset host/CDN","Always include the scheme (`https://`) — bare hostnames are invalid here","Confirm the value with `new URL(value)` before committing config"],"tags":["config","paths","url","validation"],"backgroundTag":"invalid-url-format","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}