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

  1. Inspect the shard map and use PageserverProtocol::Grpc if grpc_url is the populated field
  2. Fix the source of the connection info so libpq_url is emitted for every pageserver in the shard
  3. Fall back: try Libpq, and on this error retry with Grpc
  4. 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

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


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