sveltejs/kit · error
The `$app/service-worker` module can only be imported into a
Error message
The `$app/service-worker` module can only be imported into a service worker
What it means
In development, importing `$app/service-worker` from anywhere other than an actual service worker global scope throws immediately. The module exposes build assets and paths that only make sense inside a service worker. This is a dev-time guard against accidentally bundling service-worker-only code into the app or server.
Source
Thrown at packages/kit/src/runtime/app/service-worker/index.js:22
import { DEV } from 'esm-env';
/**
* The execution context of a service worker. This export exists to make it easier to
* use service workers with the correct types, provided the importing module is governed
* by a `tsconfig.json` that extends [`$app/tsconfig/service-worker`](https://svelte.dev/docs/kit/$app-tsconfig-service-worker).
*
*/
export const self = /** @type {ServiceWorkerGlobalScope} */ (
/** @type {unknown} */ (globalThis.self)
);
if (DEV) {
if (
typeof ServiceWorkerGlobalScope === 'undefined' ||
!(self instanceof ServiceWorkerGlobalScope)
) {
throw new Error('The `$app/service-worker` module can only be imported into a service worker');
}
}
View on GitHub (pinned to 03f1687fe6)
Solutions
- Ensure `$app/service-worker` is only imported from the `src/service-worker.js` entry
- Extract shared values (e.g. cache names) into a separate module imported by both sides, without touching `$app/service-worker` in app code
- Mock or exclude the module in tests (e.g. vi.mock('$app/service-worker'))
Example fix
// before (shared.js, imported by app)
import { version } from '$app/service-worker';
export const CACHE = `cache-${version}`;
// after (shared.js)
export const CACHE_PREFIX = 'cache';
// service-worker.js
import { version } from '$app/service-worker';
import { CACHE_PREFIX } from './shared';
const CACHE = `${CACHE_PREFIX}-${version}`; Defensive patterns
Strategy: type-guard
Validate before calling
if (typeof ServiceWorkerGlobalScope !== 'undefined' && self instanceof ServiceWorkerGlobalScope) {
import('$app/service-worker').then(initServiceWorkerLogic);
} Type guard
const inServiceWorker = typeof ServiceWorkerGlobalScope !== 'undefined' && self instanceof ServiceWorkerGlobalScope;
Try / catch
try {
const sw = await import('$app/service-worker');
useAssets(sw);
} catch (e) {
if (e.message.includes('only be imported into a service worker')) {
console.warn('$app/service-worker used outside a service worker; skipping');
} else throw e;
} Prevention
- Only import $app/service-worker from src/service-worker.js
- Keep shared modules free of $app/* service-worker imports
- Mock the module in unit tests and non-SW environments
When it happens
Trigger: Importing `$app/service-worker` in a component, `load` function, or server module; a shared module that the service worker imports also being imported by app code; running tests in a non-ServiceWorkerGlobalScope environment with DEV true.
Common situations: Moving shared constants into a file that imports `build`, `files`, or `version` from `$app/service-worker`; importing the service worker source into a unit test; misconfigured bundler entry points.
Related errors
- The `csp.directives['trusted-types']` option must include 's
- Cannot import `$app/*` modules other than `$app/env` inside
- Cannot use `match(...)` inside a service worker, as it depen
- Can only disable scroll handling during navigation
- `$app/environment` is deprecated, use `$app/env` instead
AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02).
Data as JSON: /api/errors/7f03a61ccf8176c2.
Report an issue: GitHub.