neondatabase/neon · error

failed to get list of walsenders: {}

Error message

failed to get list of walsenders: {}

What it means

check() runs `select count(*) from pg_stat_replication where application_name != 'walproposer'` to keep the compute from being suspended while (logical) walsenders are attached. This specific error fires when cli.query_one() itself fails; the column-conversion failure is a separate error ('failed to parse walsenders count'). On failure the monitor reports downtime and reconnects, same as other check() errors.

Source

Thrown at compute_tools/src/monitor.rs:291

        // N.B. walproposer doesn't currently show up in pg_stat_replication,
        // but protect if it will.
        const WS_COUNT_QUERY: &str =
            "select count(*) from pg_stat_replication where application_name != 'walproposer';";
        match cli.query_one(WS_COUNT_QUERY, &[]) {
            Ok(r) => match r.try_get::<&str, i64>("count") {
                Ok(num_ws) => {
                    if num_ws > 0 {
                        self.last_active = Some(Utc::now());
                        return Ok(());
                    }
                }
                Err(e) => {
                    let err: anyhow::Error = e.into();
                    return Err(err.context("failed to parse walsenders count"));
                }
            },
            Err(e) => {
                return Err(anyhow::anyhow!("failed to get list of walsenders: {}", e));
            }
        }

        // Don't suspend compute if there is an active logical replication subscription
        //
        // `where pid is not null` – to filter out read only computes and subscription on branches
        const LOGICAL_SUBSCRIPTIONS_QUERY: &str =
            "select count(*) from pg_stat_subscription where pid is not null;";
        match cli.query_one(LOGICAL_SUBSCRIPTIONS_QUERY, &[]) {
            Ok(row) => match row.try_get::<&str, i64>("count") {
                Ok(num_subscribers) => {
                    if num_subscribers > 0 {
                        self.last_active = Some(Utc::now());
                        return Ok(());
                    }
                }
                Err(e) => {
                    return Err(anyhow::anyhow!(

View on GitHub (pinned to 8f60b04da4)

Solutions

  1. Read the nested error to distinguish connection loss from timeout
  2. Rely on the monitor's built-in reconnect: single failures are logged and retried every 500ms
  3. If persistent, verify Postgres health and pg_stat_replication is queryable as cloud_admin
  4. When using logical replication, expect walsender counts to keep computes awake - plan monitor logs accordingly
Defensive patterns

Strategy: retry

Try / catch

match cli.query_one(WS_COUNT_QUERY, &[]) {
    Ok(r) => { let n: i64 = r.get("count"); /* keep alive if n > 0 */ }
    Err(e) => { error!("failed to get list of walsenders: {e}"); client = conf.connect(NoTls); }
}

Prevention

When it happens

Trigger: query_one on pg_stat_replication returns Err: dropped connection, statement timeout, server restart, or the view being inaccessible during recovery transitions.

Common situations: Logical replication subscribers connected when the monitor connection breaks; computes with walproposer activity being polled during suspension handoff; transient errors during Postgres shutdown sequences.

Related errors


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