sveltejs/kit · error · Error

received LISTEN_PID ${listen_pid} but current process id is

Error message

received LISTEN_PID ${listen_pid} but current process id is ${process.pid}

What it means

@sveltejs/adapter-node supports systemd socket activation via the sd_listen_fds protocol. When LISTEN_PID is set it must match the PID of the process that actually received the inherited socket file descriptors. If it points at a different process, the fds belong to someone else, so the adapter refuses to start rather than silently grabbing the wrong socket.

Source

Thrown at packages/adapter-node/src/index.js:21

import process from 'node:process';
import { handler } from './handler.js';
import { env, timeout_env } from './env.js';
import { rm } from 'node:fs/promises';
import { format_listening_address } from './utils.js';

export const path = env('SOCKET_PATH', false);
export const host = env('HOST', '0.0.0.0');
export const port = env('PORT', !path && '3000');

const shutdown_timeout = parseInt(env('SHUTDOWN_TIMEOUT', '30'));
const idle_timeout = parseInt(env('IDLE_TIMEOUT', '0'));
const listen_pid = parseInt(env('LISTEN_PID', '0'));
const listen_fds = parseInt(env('LISTEN_FDS', '0'));
// https://www.freedesktop.org/software/systemd/man/latest/sd_listen_fds.html
const SD_LISTEN_FDS_START = 3;

if (listen_pid !== 0 && listen_pid !== process.pid) {
	throw new Error(`received LISTEN_PID ${listen_pid} but current process id is ${process.pid}`);
}
if (listen_fds > 1) {
	throw new Error(
		`only one socket is allowed for socket activation, but LISTEN_FDS was set to ${listen_fds}`
	);
}

const socket_activation = listen_pid === process.pid && listen_fds === 1;

let requests = 0;
/** @type {NodeJS.Timeout | void} */
let shutdown_timeout_id;
/** @type {NodeJS.Timeout | void} */
let idle_timeout_id;

const httpServer = http.createServer();

const keep_alive_timeout = timeout_env('KEEP_ALIVE_TIMEOUT');

View on GitHub (pinned to 03f1687fe6)

Solutions

  1. Ensure the node process itself is the one systemd/socket-activation hands the socket to — run it as the direct child of the activating supervisor
  2. Unset LISTEN_PID (and LISTEN_FDS) if you are not intentionally using socket activation: `env -u LISTEN_PID -u LISTEN_FDS node build`
  3. If a wrapper script is needed, have it exec the node process (exec node build) so the PID stays the same
  4. Configure systemd with Type=exec/simple so the service PID is the one that gets LISTEN_PID

Example fix

# before
LISTEN_PID=1234 ./run.sh   # run.sh spawns node as a child
# after
exec node build            # same PID inherits and validates LISTEN_PID
Defensive patterns

Strategy: validation

Validate before calling

if (process.env.LISTEN_PID && parseInt(process.env.LISTEN_PID) !== process.pid) {
  delete process.env.LISTEN_PID; // or fail fast with a clear message before starting the server
}

Type guard

const socketActivationValid = (env = process.env) =>
  !env.LISTEN_PID || parseInt(env.LISTEN_PID, 10) === process.pid;

Try / catch

try {
  startServer();
} catch (err) {
  if (/LISTEN_PID/.test(err.message)) {
    console.error('Socket activation PID mismatch — check your supervisor/wrapper.');
    process.exit(1);
  }
  throw err;
}

Prevention

When it happens

Trigger: LISTEN_PID is set in the environment to a nonzero value that does not equal process.pid at server startup in packages/adapter-node/src/index.js.

Common situations: Running the server under a supervisor or wrapper (shell script, daemonizing tool, container init) that received the socket but spawns the node process as a child, so the child inherits LISTEN_PID pointing at the parent PID; manually exporting LISTEN_PID for testing; using systemd socket activation with a forking service Type.

Related errors


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