{"record":{"id":"e87239f41bf7c239","repo":"sveltejs/kit","slug":"cannot-use-match-inside-a-service-worker-a","errorCode":null,"errorMessage":"Cannot use `match(...)` inside a service worker, as it depends on the SvelteKit client instance","messagePattern":"Cannot use `match\\(\\.\\.\\.\\)` inside a service worker, as it depends on the SvelteKit client instance","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/kit/src/runtime/app/paths/internal/client.js","lineNumber":23,"sourceCode":"/** @import { RouteId } from '$app/types' */\nimport { payload } from '../../../client/payload.js';\n\nexport const base = payload.base ?? __SVELTEKIT_PATHS_BASE__;\nexport const assets = payload.assets ?? base ?? __SVELTEKIT_PATHS_ASSETS__;\nexport const app_dir = __SVELTEKIT_APP_DIR__;\nexport const hash_routing = __SVELTEKIT_HASH_ROUTING__;\n\n/**\n * We make this configurable per-environment so that it's possible to import `$app/paths`\n * into a service worker without importing the entire client\n * @param {URL | string} _url\n * @returns {Promise<{ [K in RouteId]: { id: K; params: import('$app/types').RouteParams<K>; } }[RouteId] | null>}\n */\n// eslint-disable-next-line @typescript-eslint/require-await\nexport let match_implementation = async (_url) => {\n\t// @ts-ignore\n\tif (typeof ServiceWorkerGlobalScope !== 'undefined' && self instanceof ServiceWorkerGlobalScope) {\n\t\tthrow new Error(\n\t\t\t'Cannot use `match(...)` inside a service worker, as it depends on the SvelteKit client instance'\n\t\t);\n\t}\n\n\treturn null;\n};\n\n/**\n * @param {typeof match_implementation} fn\n */\nexport function set_match_implementation(fn) {\n\tmatch_implementation = fn;\n}\n","sourceCodeStart":5,"sourceCodeEnd":37,"githubUrl":"https://github.com/sveltejs/kit/blob/03f1687fe612ce3d2d9131139b5b188d9cf90c64/packages/kit/src/runtime/app/paths/internal/client.js#L5-L37","documentation":"match(...) from $app/paths relies on the running SvelteKit client instance to know the app's routes. Service workers run in a separate global scope without that client, so SvelteKit throws if match is invoked inside a ServiceWorkerGlobalScope, offering a null-returning stub otherwise.","triggerScenarios":"Importing match from $app/paths (or $service-worker re-exports) and calling it inside a service worker script — detected via `self instanceof ServiceWorkerGlobalScope`.","commonSituations":"Writing custom service workers that try to reuse app routing helpers, copying client-side path resolution code into sw.js, or sharing a module between app and service worker that calls match at module scope.","solutions":["In the service worker, match URLs yourself (e.g. use the route manifest passed to the sw build, or simple regex/pattern matching)","Keep match() usage in app code only; guard shared modules so it is not called in the sw context","Use $service-worker's `build`, `files`, and `version` exports for caching logic instead of runtime route matching","If the sw just needs to decide which requests to handle, check request.destination/url patterns directly"],"exampleFix":"// before (service worker)\nimport { match } from '$app/paths';\nconst routes = await match(request.url);\n// after\nimport { build, files, version } from '$service-worker';\nconst cached = [...build, ...files]; // decide by URL patterns instead","handlingStrategy":"type-guard","validationCode":"if (typeof ServiceWorkerGlobalScope !== 'undefined' && self instanceof ServiceWorkerGlobalScope) {\n  // do NOT import/call match() here; use $service-worker exports instead\n}","typeGuard":"const inServiceWorker = () =>\n  typeof ServiceWorkerGlobalScope !== 'undefined' && self instanceof ServiceWorkerGlobalScope;","tryCatchPattern":"let routes = null;\ntry {\n  routes = await match(url);\n} catch (e) {\n  if (e.message.includes('inside a service worker')) {\n    routes = matchUrlManually(url); // sw-local pattern matching\n  } else throw e;\n}","preventionTips":["Never import $app/paths helpers into service worker code","Use $service-worker (build, files, version) for sw logic","Guard shared modules with a ServiceWorkerGlobalScope check before calling match","Keep routing logic for sw simple (URL prefixes/patterns) rather than reusing app route resolution"],"tags":["sveltekit","service-worker","paths","unsupported-context"],"backgroundTag":"api-unsupported-in-service-worker","analyzedSha":"03f1687fe612ce3d2d9131139b5b188d9cf90c64","analyzedAt":"2026-09-02T02:01:50.504Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-09T06:17:21.866Z"}