neondatabase/neon · error

could not query active_time: {}

Error message

could not query active_time: {}

What it means

get_database_stats(), the helper behind the experimental activity monitor, runs query_one over pg_stat_database (sum of active_time and sessions for non-system databases). This error means that query returned Err - despite the message mentioning only active_time, it covers the whole statistics query. The caller wraps it further as 'could not get database statistics' and the monitor reports downtime then reconnects.

Source

Thrown at compute_tools/src/monitor.rs:423

fn get_database_stats(cli: &mut Client) -> anyhow::Result<(f64, i64)> {
    // Filter out `postgres` database as `compute_ctl` and other monitoring tools
    // like `postgres_exporter` use it to query Postgres statistics.
    // Use explicit 8 bytes type casts to match Rust types.
    let stats = cli.query_one(
        "SELECT pg_catalog.coalesce(pg_catalog.sum(active_time), 0.0)::pg_catalog.float8 AS total_active_time,
            pg_catalog.coalesce(pg_catalog.sum(sessions), 0)::pg_catalog.bigint AS total_sessions
        FROM pg_catalog.pg_stat_database
        WHERE datname NOT IN (
                'postgres',
                'template0',
                'template1'
            );",
        &[],
    );
    let stats = match stats {
        Ok(stats) => stats,
        Err(e) => {
            return Err(anyhow::anyhow!("could not query active_time: {}", e));
        }
    };

    let active_time: f64 = match stats.try_get("total_active_time") {
        Ok(active_time) => active_time,
        Err(e) => return Err(anyhow::anyhow!("could not get total_active_time: {}", e)),
    };

    let sessions: i64 = match stats.try_get("total_sessions") {
        Ok(sessions) => sessions,
        Err(e) => return Err(anyhow::anyhow!("could not get total_sessions: {}", e)),
    };

    Ok((active_time, sessions))
}

// Figure out the most recent state change time across all client backends.
// If there is currently active backend, timestamp will be `Utc::now()`.

View on GitHub (pinned to 8f60b04da4)

Solutions

  1. Read the appended tokio_postgres error to identify connection vs timeout vs server failure
  2. Confirm the compute reached Running state and Postgres accepts connections
  3. Accept transient single errors - the monitor reconnects automatically
  4. For recurring timeouts, tune statement_timeout or reduce load
Defensive patterns

Strategy: retry

Try / catch

let stats = match cli.query_one(GET_DB_STATS_SQL, &[]) {
    Ok(row) => row,
    Err(e) => {
        error!("could not query active_time: {e}");
        client = conf.connect(NoTls);
        continue; // next monitor tick
    }
};

Prevention

When it happens

Trigger: query_one on pg_stat_database fails: dead connection (is_closed() can miss it), statement timeout, or Postgres restarting/crashing while the monitor polls every 500ms.

Common situations: Compute suspend/resume racing the monitor; overloaded computes timing out on catalog views; development environments with frequently killed Postgres processes.

Related errors


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