neondatabase/neon · error
failed to parse autovacuum workers count: {}
Error message
failed to parse autovacuum workers count: {} What it means
The autovacuum-count query (`select count(*) from pg_stat_activity where backend_type = 'autovacuum worker'`) succeeded, but r.try_get::<&str, i64>("count") failed - the 'count' column could not be converted to i64. Since count(*) is int8, this points at type/schema drift or a mangled row rather than a runtime value issue. The error aborts check() and is handled as downtime plus reconnect.
Source
Thrown at compute_tools/src/monitor.rs:335
"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") {
Ok(num_workers) => {
if num_workers > 0 {
self.last_active = Some(Utc::now());
return Ok(());
};
}
Err(e) => {
return Err(anyhow::anyhow!(
"failed to parse autovacuum workers count: {}",
e
));
}
},
Err(e) => {
return Err(anyhow::anyhow!(
"failed to get list of autovacuum workers: {}",
e
));
}
}
Ok(())
}
}
// Hang on condition variable waiting until the compute status is `Running`.View on GitHub (pinned to 8f60b04da4)
Solutions
- Cast explicitly in SQL: `count(*)::pg_catalog.bigint`
- Read the inner FromSql error to see expected vs actual type
- Keep the query and the try_get type in sync when modifying monitor queries
- Cover monitor queries with integration tests against your shipped PG version
Example fix
// before
const AUTOVACUUM_COUNT_QUERY: &str =
"select count(*) from pg_stat_activity where backend_type = 'autovacuum worker'";
// after
const AUTOVACUUM_COUNT_QUERY: &str =
"select count(*)::pg_catalog.bigint from pg_stat_activity where backend_type = 'autovacuum worker'"; Defensive patterns
Strategy: validation
Validate before calling
// pin the wire type in SQL so try_get::<_, i64> cannot mismatch
const AUTOVACUUM_COUNT_QUERY: &str =
"select count(*)::pg_catalog.bigint from pg_stat_activity where backend_type = 'autovacuum worker'"; 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 r.try_get::<&str, i64>("count") {
Ok(n) => { /* use n */ }
Err(e) => warn!("autovacuum count unreadable, skipping: {e}"), // non-fatal for the check
} Prevention
- Cast count() to ::bigint whenever the Rust side reads i64
- Keep SQL and try_get types in one place when editing monitor queries
- Add tests for monitor queries per supported PG version
When it happens
Trigger: try_get mismatch: 'count' column not of SQL type INT8, column absent, or a Postgres version/build whose count output type differs.
Common situations: Postgres major-version upgrades or patched builds changing system-view expression types; query edits that drop the 'count' alias without updating the Rust side.
Understand the failure class
- Parsing and encoding errors: unexpected token, malformed input — why parsers reject input and how to find the real culprit.
Related errors
- failed to get list of autovacuum workers: {}
- could not get backends state change: {}
- failed to parse 'pg_stat_subscription' count: {}
- could not get total_active_time: {}
- could not get total_sessions: {}
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/4b49b4f656f5a0be.
Report an issue: GitHub.