neondatabase/neon · error
no libpq_url for shard {shard_index}
Error message
no libpq_url for shard {shard_index} What it means
Thrown by PageserverConnectionInfo::shard_url() in neon's compute_api when the Libpq protocol is requested but the first pageserver entry for the shard has libpq_url: None. libpq_url is Option<String> on PageserverShardConnectionInfo, populated from control-plane data; this error means the shard map knows about the pageserver but has no postgres-protocol connection string for it. It is the libpq twin of the 'no grpc_url for shard' error.
Source
Thrown at libs/compute_api/src/spec.rs:352
// Just use the first pageserver in the list. That's good enough for this
// convenience routine; if you need more control, like round robin policy or
// failover support, roll your own. (As of this writing, we never have more than
// one pageserver per shard anyway, but that will change in the future.)
let pageserver = shard
.pageservers
.first()
.ok_or(anyhow::anyhow!("must have at least one pageserver"))?;
let result = match protocol {
PageserverProtocol::Grpc => pageserver
.grpc_url
.as_ref()
.ok_or(anyhow::anyhow!("no grpc_url for shard {shard_index}"))?,
PageserverProtocol::Libpq => pageserver
.libpq_url
.as_ref()
.ok_or(anyhow::anyhow!("no libpq_url for shard {shard_index}"))?,
};
Ok(result)
}
}
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
pub struct PageserverShardInfo {
pub pageservers: Vec<PageserverShardConnectionInfo>,
}
#[derive(Clone, Debug, Deserialize, Serialize, Eq, PartialEq)]
pub struct PageserverShardConnectionInfo {
pub id: Option<NodeId>,
pub libpq_url: Option<String>,
pub grpc_url: Option<String>,
}
#[derive(Clone, Debug, Default, Deserialize, Serialize)]View on GitHub (pinned to 8f60b04da4)
Solutions
- Inspect the shard map and use PageserverProtocol::Grpc if grpc_url is the populated field
- Fix the source of the connection info so libpq_url is emitted for every pageserver in the shard
- Fall back: try Libpq, and on this error retry with Grpc
- For multi-pageserver shards, pick a pageserver entry that actually has the URL you need instead of relying on first()
Example fix
// before
let url = conn_info.shard_url(shard_number, PageserverProtocol::Libpq)?;
// after
let url = conn_info
.shard_url(shard_number, PageserverProtocol::Libpq)
.or_else(|_| conn_info.shard_url(shard_number, PageserverProtocol::Grpc))?; Defensive patterns
Strategy: validation
Validate before calling
// Before calling shard_url with Libpq, confirm the field exists:
fn has_libpq_url(ci: &PageserverConnectionInfo, sn: ShardNumber) -> bool {
let idx = ShardIndex { shard_number: sn, shard_count: ci.shard_count };
ci.shards
.get(&idx)
.and_then(|s| s.pageservers.first())
.and_then(|p| p.libpq_url.as_ref())
.is_some()
} Try / catch
// Degrade to the other protocol when the preferred URL is absent:
let url = conn_info
.shard_url(sn, PageserverProtocol::Libpq)
.or_else(|_| conn_info.shard_url(sn, PageserverProtocol::Grpc))?; Prevention
- Keep the control-plane shard JSON populated with both libpq_url and grpc_url whenever the pageserver offers both
- Log which URL fields are missing when building PageserverConnectionInfo so skew is visible early
- Do not assume the default protocol is always available; check the Option fields first
When it happens
Trigger: Calling shard_url(shard_number, PageserverProtocol::Libpq) when the shard's first pageservers entry lacks libpq_url (null in the JSON). Typical when the control plane only fills grpc_url, or a test constructs PageserverShardConnectionInfo { id, grpc_url: Some(...), libpq_url: None }.
Common situations: Newer deployments that moved pageservers to gRPC-only management; stale or partial control-plane state after an upgrade; unit tests building shard info by hand that forget the libpq field; asking for the default protocol on a shard that was never given a postgres connection string.
Related errors
- no grpc_url for shard {shard_index}
- invalid connstring URL: {err}
- invalid protocol scheme: {scheme}
- empty connection string
- must have at least one pageserver
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/8192b32419060526.
Report an issue: GitHub.