neondatabase/neon · error
file cache size query returned no rows
Error message
file cache size query returned no rows
What it means
`FileCache::get_file_cache_size` runs `SELECT pg_size_bytes(current_setting('neon.file_cache_size_limit'))` via `query_with_retry` and expects exactly one row containing the current cache size in bytes. Postgres returns a row for this scalar SELECT even when the setting is empty, so a zero-row result means the query path itself is broken (severe connection anomaly or a misbehaving client), not a missing setting.
Source
Thrown at libs/vm_monitor/src/filecache.rs:239
.await
.context("failed to execute query a second time")
}
}
}
/// Get the current size of the file cache.
#[tracing::instrument(skip_all)]
pub async fn get_file_cache_size(&mut self) -> anyhow::Result<u64> {
self.query_with_retry(
// The file cache GUC variable is in MiB, but the conversion with
// pg_size_bytes means that the end result we get is in bytes.
"SELECT pg_size_bytes(current_setting('neon.file_cache_size_limit'));",
&[],
)
.await
.context("failed to query pg for file cache size")?
.first()
.ok_or_else(|| anyhow!("file cache size query returned no rows"))?
// pg_size_bytes returns a bigint which is the same as an i64.
.try_get::<_, i64>(0)
// Since the size of the table is not negative, the cast is sound.
.map(|bytes| bytes as u64)
.context("failed to extract file cache size from query result")
}
/// Attempt to set the file cache size, returning the size it was actually
/// set to.
#[tracing::instrument(skip_all, fields(%num_bytes))]
pub async fn set_file_cache_size(&mut self, num_bytes: u64) -> anyhow::Result<u64> {
let max_bytes = self
// The file cache GUC variable is in MiB, but the conversion with pg_size_bytes
// means that the end result we get is in bytes.
.query_with_retry(
"SELECT pg_size_bytes(current_setting('neon.max_file_cache_size'));",
&[],
)View on GitHub (pinned to 8f60b04da4)
Solutions
- Check vm-monitor to compute-node postgres connection health and retry the operation
- If in a test, make the mocked query client return one row for `SELECT pg_size_bytes(current_setting('neon.file_cache_size_limit'))`
- Inspect logs for the preceding `failed to query pg for file cache size` context to find the underlying connection error
- Verify you are connected to a Neon compute node where the `neon.file_cache_size_limit` GUC exists
Defensive patterns
Strategy: retry
Try / catch
match filecache.get_file_cache_size().await {
Ok(size) => { /* use size */ }
Err(e) if e.to_string().contains("no rows") => {
// scalar SELECT returning nothing is a transport anomaly: reconnect and retry
reconnect().await?;
let size = filecache.get_file_cache_size().await?;
}
Err(e) => return Err(e),
} Prevention
- Monitor connection pool health between vm-monitor and postgres
- In tests, always program mocked SQL clients with a row for scalar settings queries
- Treat zero rows on a scalar SELECT as a connection red flag, never as a normal value
When it happens
Trigger: Calling `get_file_cache_size()` when the underlying postgres connection returns zero rows for the scalar SELECT — a degraded pool connection, a test-mocked sqlx client that forgot to enqueue a row for this statement, or a proxy mangling result sets.
Common situations: Unit tests with mocked SQL clients missing row fixtures; flaky connectivity between vm-monitor and the compute node's postgres; running the monitor against a non-Neon postgres or through a misconfigured pgbouncer/proxy.
Related errors
- max file cache size query returned no rows
- pg_ctl failed, exit code: {}, stdout: {}, stderr: {}
- incompatible resource_multipler and spread_factor
- Non-overlapping bounds: other.max = {} was less than self.mi
- Non-overlappinng bounds: self.max = {} was less than other.m
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/3c3f859e6b8d3634.
Report an issue: GitHub.