neondatabase/neon · critical
shard {shard_index} missing from pageserver_connection_info
Error message
shard {shard_index} missing from pageserver_connection_info shard map What it means
When expanding a sharded pageserver connstring, compute_tools iterates shard numbers 0..shard_count and looks each up in conninfo.shards. For some shard index the map had no entry, so the per-shard pageserver list could not be built. The connstring's shard_count disagrees with the shard map it carries - malformed or truncated control-plane input. (The next line also has a hard expect on a non-empty pageservers list, a sibling failure mode.)
Source
Thrown at compute_tools/src/config.rs:94
"# from compute spec's pageserver_connection_info.stripe_size field"
)?;
writeln!(file, "neon.stripe_size={stripe_size}")?;
}
let mut libpq_urls: Option<Vec<String>> = Some(Vec::new());
let num_shards = if conninfo.shard_count.0 == 0 {
1 // unsharded, treat it as a single shard
} else {
conninfo.shard_count.0
};
for shard_number in 0..num_shards {
let shard_index = ShardIndex {
shard_number: ShardNumber(shard_number),
shard_count: conninfo.shard_count,
};
let info = conninfo.shards.get(&shard_index).ok_or_else(|| {
anyhow::anyhow!(
"shard {shard_index} missing from pageserver_connection_info shard map"
)
})?;
let first_pageserver = info
.pageservers
.first()
.expect("must have at least one pageserver");
// Add the libpq URL to the array, or if the URL is missing, reset the array
// forgetting any previous entries. All servers must have a libpq URL, or none
// at all.
if let Some(url) = &first_pageserver.libpq_url {
if let Some(ref mut urls) = libpq_urls {
urls.push(url.clone());
}
} else {
libpq_urls = NoneView on GitHub (pinned to 8f60b04da4)
Solutions
- Inspect the neon.pageserver_connstring GUC: the shard_count number must match the number of shard entries in the map
- Regenerate the connstring from the control plane after resharding completes so count and map are consistent
- For unsharded tenants keep shard_count at 0, which the code treats as a single shard and skips the map
Example fix
# before: shard_count=2 with only shard 0 mapped -> error
# after (GUC payload shape)
shard_count=2;shards={ 0: 'host=ps-0', 1: 'host=ps-1' } # every index 0..count-1 present Defensive patterns
Strategy: validation
Validate before calling
// Validate shard-map completeness before expanding the connstring
let n = if conninfo.shard_count.0 == 0 { 1 } else { conninfo.shard_count.0 };
for i in 0..n {
let idx = ShardIndex { shard_number: ShardNumber(i), shard_count: conninfo.shard_count };
let info = conninfo.shards.get(&idx).ok_or(anyhow!("shard {idx} missing"))?;
if info.pageservers.is_empty() { anyhow::bail!("shard {idx} has no pageservers"); }
} Type guard
fn shard_map_complete(conninfo: &PageserverConnectionInfo) -> bool {
let n = if conninfo.shard_count.0 == 0 { 1 } else { conninfo.shard_count.0 };
(0..n).all(|i| {
let idx = ShardIndex { shard_number: ShardNumber(i), shard_count: conninfo.shard_count };
conninfo.shards.get(&idx).map(|s| !s.pageservers.is_empty()).unwrap_or(false)
})
} Try / catch
// Config error at startup: surface which shard is missing instead of retrying
if let Some(missing) = (0..n).map(|i| /* build idx */).find(|idx| !conninfo.shards.contains_key(idx)) {
return Err(anyhow!("incomplete shard map: missing shard {missing} of {}", conninfo.shard_count));
} Prevention
- Have the control plane construct shard maps and shard_count in one function so they cannot diverge
- After resharding, verify 0..shard_count all present before publishing the connstring GUC
- Replace the sibling .expect("must have at least one pageserver") with a checked error too - it panics on the same malformed input
When it happens
Trigger: PageserverConnectionInfo parsed with shard_count > 0 but whose shards map lacks an entry for one of the shard indices in 0..shard_count; e.g. a connstring built for N shards but embedding only N-1 shard entries.
Common situations: Control-plane bugs during shard resharding (shard_count bumped before shard map updated); hand-edited or templated connstrings; version skew in how shard maps are serialized into the GUC; partially migrated sharded tenants.
Related errors
- pageserver connection information should be provided
- safekeeper connstrings should be provided
- tenant id should be provided
- timeline id should be provided
- Remote extensions are not configured
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/d7ed94e3f4435fa5.
Report an issue: GitHub.