neondatabase/neon · error

failed to parse 'pg_stat_subscription' count: {}

Error message

failed to parse 'pg_stat_subscription' count: {}

What it means

The subscription-count query succeeded, but row.try_get::<&str, i64>("count") failed - the returned 'count' column could not be converted to i64. count(*) normally returns int8 which maps to i64, so this indicates schema/type drift (a different wire type or missing column) rather than a value problem. It propagates out of check() as a monitor error (downtime + reconnect).

Source

Thrown at compute_tools/src/monitor.rs:309

                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!(
                        "failed to parse 'pg_stat_subscription' count: {}",
                        e
                    ));
                }
            },
            Err(e) => {
                return Err(anyhow::anyhow!(
                    "failed to get list of active logical replication subscriptions: {}",
                    e
                ));
            }
        }

        // Do not suspend compute if autovacuum is running
        const AUTOVACUUM_COUNT_QUERY: &str =
            "select count(*) from pg_stat_activity where backend_type = 'autovacuum worker'";
        match cli.query_one(AUTOVACUUM_COUNT_QUERY, &[]) {
            Ok(r) => match r.try_get::<&str, i64>("count") {

View on GitHub (pinned to 8f60b04da4)

Solutions

  1. Add an explicit SQL cast so the wire type always matches: `count(*)::pg_catalog.bigint`
  2. Check the inner FromSql error text - it names the expected versus actual type
  3. Verify the exact query still selects a column aliased 'count' on your PG version
  4. Compare with get_database_stats which already uses explicit ::float8/::bigint casts for this reason

Example fix

// before
const LOGICAL_SUBSCRIPTIONS_QUERY: &str =
    "select count(*) from pg_stat_subscription where pid is not null;";

// after
const LOGICAL_SUBSCRIPTIONS_QUERY: &str =
    "select count(*)::pg_catalog.bigint from pg_stat_subscription where pid is not null;"
Defensive patterns

Strategy: validation

Validate before calling

// pin the wire type in SQL so try_get::<_, i64> cannot mismatch
const LOGICAL_SUBSCRIPTIONS_QUERY: &str =
    "select count(*)::pg_catalog.bigint from pg_stat_subscription where pid is not null;";

Type guard

fn count_is_int8(row: &postgres::Row, col: &str) -> bool {
    row.columns()
        .iter()
        .any(|c| c.name() == col && *c.type_() == postgres::types::Type::INT8)
}

Try / catch

match row.try_get::<&str, i64>("count") {
    Ok(n) => { /* use n */ }
    Err(e) => warn!("skipping subscription count, unexpected type: {e}"), // don't fail the whole check
}

Prevention

When it happens

Trigger: try_get type mismatch: the 'count' column's SQL type is not Type::INT8, the column is missing/renamed, or a PG version/extension changes the output type of the pg_stat_subscription count query.

Common situations: Running against an unusual Postgres build or a major-version upgrade that altered system-view output types; editing the monitor query without keeping the Rust conversion in sync.

Understand the failure class

Related errors


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