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

  1. Ensure `$app/service-worker` is only imported from the `src/service-worker.js` entry
  2. Extract shared values (e.g. cache names) into a separate module imported by both sides, without touching `$app/service-worker` in app code
  3. 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

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


AI-assisted analysis of sveltejs/kit@03f1687fe6 (2026-09-02). Data as JSON: /api/errors/7f03a61ccf8176c2. Report an issue: GitHub.