sveltejs/kit · error · Error

received 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.

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.

Appendix: 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)