pbakaus/impeccable · error

SvelteKit live adapter requires a numeric port

Error message

SvelteKit live adapter requires a numeric port

What it means

Thrown by applySvelteKitLiveAdapter() in live/sveltekit-adapter.mjs when the 'port' argument fails Number.isFinite(Number(port)). The adapter needs a concrete numeric port to bake into the generated Svelte live root component (so the client knows where to poll); a non-numeric, NaN, or Infinity port cannot be embedded. The guard runs before any detection or file writes, so nothing is mutated on failure.

Source

Thrown at skill/scripts/live/sveltekit-adapter.mjs:64

  if (!hasTemplateMarkers) return null;

  const hasSvelteConfig = fs.existsSync(path.join(cwd, 'svelte.config.js'))
    || fs.existsSync(path.join(cwd, 'svelte.config.mjs'))
    || fs.existsSync(path.join(cwd, 'svelte.config.cjs'))
    || fs.existsSync(path.join(cwd, 'svelte.config.ts'));
  const hasKitPackage = packageHasSvelteKit(cwd);
  if (!hasSvelteConfig && !hasKitPackage) return null;

  return {
    appHtml,
    layoutFile: findSvelteKitLayout(cwd),
    rootComponent: SVELTE_LIVE_ROOT_COMPONENT,
  };
}

export function applySvelteKitLiveAdapter({ cwd = process.cwd(), port, token, config = null } = {}) {
  if (!Number.isFinite(Number(port))) {
    throw new Error('SvelteKit live adapter requires a numeric port');
  }
  const detected = detectSvelteKitProject(cwd, config);
  if (!detected) return null;

  ensureSvelteLiveRootComponent(cwd, Number(port), token);

  const layoutRel = detected.layoutFile;
  const layoutAbs = path.join(cwd, layoutRel);
  fs.mkdirSync(path.dirname(layoutAbs), { recursive: true });
  const layoutExisted = fs.existsSync(layoutAbs);
  const before = layoutExisted ? fs.readFileSync(layoutAbs, 'utf-8') : defaultSvelteLayout();
  const after = patchSvelteLayout(before, { rev: svelteAdapterRev(token) });
  fs.writeFileSync(layoutAbs, after, 'utf-8');

  return {
    file: layoutRel,
    adapter: 'sveltekit',
    inserted: after !== before || !layoutExisted,

View on GitHub (pinned to d14711ae3d)

Solutions

  1. Pass a finite number: applySvelteKitLiveAdapter({cwd, port: 4321, token}).
  2. Coerce and validate from env: const port = Number(process.env.PORT || 4321); guard with Number.isFinite before calling.
  3. Ensure the CLI flag parser yields a number, not a string-only-when-set value.

Example fix

// before
applySvelteKitLiveAdapter({ cwd, port: process.env.PORT, token })
// after
const port = Number(process.env.PORT || 4321)
applySvelteKitLiveAdapter({ cwd, port, token })
Defensive patterns

Strategy: validation

Validate before calling

const portNum = Number(port);
if (!Number.isFinite(portNum)) throw new Error('port must be a finite number');
applySvelteKitLiveAdapter({ cwd, port: portNum, token });

Type guard

function isFinitePort(v: unknown): v is number {
  return Number.isFinite(typeof v === 'number' ? v : Number(v));
}

Prevention

When it happens

Trigger: applySvelteKitLiveAdapter({cwd, port, token}) is called with port = undefined, null, a non-numeric string like 'abc', NaN, or Infinity. Note Number('3000') would pass, but Number(undefined) = NaN fails.

Common situations: Port read from an env var that was unset (PORT -> undefined); CLI flag parsed as a flag presence boolean instead of a number; default port removed during a refactor; caller passed the raw string 'abc' by mistake; Infinity from a bad division.

Related errors


AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13). Data as JSON: /api/errors/51513551f753f79e. Report an issue: GitHub.