neondatabase/neon · error
empty connection string
Error message
empty connection string
What it means
PageserverConnectionInfo::from_connstr parses a legacy comma-separated list of libpq connection strings (ComputeSpec::pageserver_connstring or the neon.pageserver_connstring GUC) into shard info. Each comma-separated element becomes one shard, so the count is always at least one for any input including the empty string; the 0-shard arm is a defensive guard that effectively fires only if the split yields no elements at all.
Source
Thrown at libs/compute_api/src/spec.rs:276
/// the 'pageserver_connection_info' field should be used instead.
impl PageserverConnectionInfo {
pub fn from_connstr(
connstr: &str,
stripe_size: Option<ShardStripeSize>,
) -> Result<PageserverConnectionInfo, anyhow::Error> {
let shard_infos: Vec<_> = connstr
.split(',')
.map(|connstr| PageserverShardInfo {
pageservers: vec![PageserverShardConnectionInfo {
id: None,
libpq_url: Some(connstr.to_string()),
grpc_url: None,
}],
})
.collect();
match shard_infos.len() {
0 => anyhow::bail!("empty connection string"),
1 => {
// We assume that if there's only connection string, it means "unsharded",
// rather than a sharded system with just a single shard. The latter is
// possible in principle, but we never do it.
let shard_count = ShardCount::unsharded();
let only_shard = shard_infos.first().unwrap().clone();
let shards = vec![(ShardIndex::unsharded(), only_shard)];
Ok(PageserverConnectionInfo {
shard_count,
stripe_size: None,
shards: shards.into_iter().collect(),
prefer_protocol: PageserverProtocol::Libpq,
})
}
n => {
if stripe_size.is_none() {
anyhow::bail!("{n} shards but no stripe_size");
}View on GitHub (pinned to 8f60b04da4)
Solutions
- Prefer the modern pageserver_connection_info field in ComputeSpec instead of the legacy connstr string
- Validate that the connstr is non-empty and contains a real libpq URL before calling from_connstr
- If you maintain a caller of from_connstr, treat zero parsed shards as invalid input and report which field was empty
Example fix
// before
let info = PageserverConnectionInfo::from_connstr(&spec.pageserver_connstring.unwrap_or_default(), stripe_size)?;
// after
let connstr = spec.pageserver_connstring.as_deref().filter(|s| !s.trim().is_empty())
.ok_or_else(|| anyhow::anyhow!("pageserver_connstring missing"))?;
let info = PageserverConnectionInfo::from_connstr(connstr, stripe_size)?; Defensive patterns
Strategy: validation
Validate before calling
let trimmed = connstr.trim();
anyhow::ensure!(!trimmed.is_empty(), "connection string is empty");
anyhow::ensure!(trimmed.starts_with("postgresql://") || trimmed.starts_with("postgres://"),
"connection string does not look like a libpq URL: {trimmed}");
let info = PageserverConnectionInfo::from_connstr(trimmed, stripe_size)?; Prevention
- Validate connstrs are non-empty libpq URLs before parsing
- Migrate specs to pageserver_connection_info so structure is validated by serde, not string splitting
When it happens
Trigger: Calling from_connstr in a way that yields zero shard entries — practically only reachable via inputs that short-circuit the split (the arm exists to future-proof the match). Real-world near-misses are empty-string connstrs, which instead produce a single empty-URL shard and fail later at connection time.
Common situations: Migrating legacy specs that still use pageserver_connstring instead of the modern pageserver_connection_info field; passing an unset env var or empty GUC value through this legacy path.
Related errors
- {n} shards but no stripe_size
- invalid compute claims scope "{s}"
- shard connection info missing for shard {}
- must have at least one pageserver
- no grpc_url for shard {shard_index}
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/6afbe6ae92eabdae.
Report an issue: GitHub.