neondatabase/neon · error

bad value in pidfile '{pid}'

Error message

bad value in pidfile '{pid}'

What it means

parse_pidfile_content first parses the pidfile as i32 and then rejects values below 1. A parseable but impossible PID (0 or negative) cannot name a process, so reading the pidfile fails with the offending value included in the message.

Source

Thrown at libs/utils/src/pid_file.rs:163

            content,
        } => {
            // XXX the read races with the write in claim_pid_file_for_pid().
            // But pids are smaller than a page, so the kernel page cache will lock for us.
            // The only problem is that we might get the old contents here.
            // Can only fix that by implementing some scheme that downgrades the
            // exclusive lock to shared lock in claim_pid_file_for_pid().
            PidFileRead::LockedByOtherProcess(parse_pidfile_content(&content)?)
        }
    };
    Ok(ret)
}

fn parse_pidfile_content(content: &str) -> anyhow::Result<Pid> {
    let pid: i32 = content
        .parse()
        .map_err(|_| anyhow::anyhow!("parse pidfile content to PID"))?;
    if pid < 1 {
        anyhow::bail!("bad value in pidfile '{pid}'");
    }
    Ok(Pid::from_raw(pid))
}

View on GitHub (pinned to 8f60b04da4)

Solutions

  1. cat the pidfile to confirm the invalid value
  2. If the file is stale (no flock holder), remove it while the service is stopped and restart
  3. Audit what wrote the invalid value so it does not recur

Example fix

# before
$ cat /var/lib/neon.pid
0
# after: with the service stopped, remove the stale file and restart
# rm /var/lib/neon.pid
systemctl start neon
Defensive patterns

Strategy: validation

Validate before calling

fn pidfile_content_is_valid(path: &std::path::Path) -> bool {
    std::fs::read_to_string(path)
        .ok()
        .and_then(|c| c.trim().parse::<i32>().ok())
        .is_some_and(|pid| pid >= 1)
}

Type guard

fn is_bad_pid_value_error(err: &anyhow::Error) -> bool {
    err.to_string().contains("bad value in pidfile")
}

Try / catch

match pid_file::read(&path) {
    Err(e) if e.to_string().contains("bad value in pidfile") => {
        // the message embeds the value; if the file is stale (no flock holder), remove it while stopped
    }
    other => other?,
}

Prevention

When it happens

Trigger: A pidfile containing '0', '-1', or another value < 1, e.g. written by a tool that zero-initializes files before forking or by corrupted state.

Common situations: Zero-filled files after an unclean shutdown; monitoring tooling writing placeholder zeros; manual edits.

Related errors


AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16). Data as JSON: /api/errors/665b69585c20479f. Report an issue: GitHub.