neondatabase/neon · error
invalid protocol scheme: {scheme}
Error message
invalid protocol scheme: {scheme} What it means
Thrown by PageserverProtocol::from_connstring() in neon's compute_api when the connstring parsed successfully as a URL but its scheme is neither postgresql/postgres (Libpq) nor grpc (Grpc). The scheme comparison is done on the lowercased scheme, so only these three spellings are accepted; everything else is rejected as an unsupported protocol.
Source
Thrown at libs/compute_api/src/spec.rs:653
Libpq,
/// A newer, gRPC-based protocol. Uses grpc:// scheme.
#[serde(rename = "grpc")]
Grpc,
}
impl PageserverProtocol {
/// Parses the protocol from a connstring scheme. Defaults to Libpq if no scheme is given.
/// Errors if the connstring is an invalid URL.
pub fn from_connstring(connstring: &str) -> anyhow::Result<Self> {
let scheme = match Url::parse(connstring) {
Ok(url) => url.scheme().to_lowercase(),
Err(url::ParseError::RelativeUrlWithoutBase) => return Ok(Self::default()),
Err(err) => return Err(anyhow!("invalid connstring URL: {err}")),
};
match scheme.as_str() {
"postgresql" | "postgres" => Ok(Self::Libpq),
"grpc" => Ok(Self::Grpc),
scheme => Err(anyhow!("invalid protocol scheme: {scheme}")),
}
}
/// Returns the URL scheme for the protocol, for use in connstrings.
pub fn scheme(&self) -> &'static str {
match self {
Self::Libpq => "postgresql",
Self::Grpc => "grpc",
}
}
}
impl Display for PageserverProtocol {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.write_str(self.scheme())
}
}
View on GitHub (pinned to 8f60b04da4)
Solutions
- Check the scheme of the connstring and change it to postgresql://, postgres://, or grpc:// as appropriate
- Make sure you passed the data-plane connstring, not the pageserver HTTP management URL
- Fix typos in the scheme (it must be exactly postgres, postgresql, or grpc, case-insensitive)
- If the string has no scheme at all, that is fine — from_connstring defaults to Libpq; only wrong schemes fail
Example fix
# before PAGESERVER_CONNSTRING="http://pageserver-0:9898" # invalid protocol scheme: http # after PAGESERVER_CONNSTRING="postgres://pageserver-0:6400" # or grpc://pageserver-0:50051
Defensive patterns
Strategy: validation
Validate before calling
// Accept only the three supported schemes before use:
fn scheme_supported(s: &str) -> bool {
url::Url::parse(s).ok()
.map(|u| matches!(u.scheme().to_lowercase().as_str(), "postgres" | "postgresql" | "grpc"))
.unwrap_or(true) // scheme-less defaults to Libpq
} Try / catch
// Distinguish scheme errors from malformed-URL errors for clearer operator messages:
match PageserverProtocol::from_connstring(s) {
Ok(p) => Ok(p),
Err(e) if e.to_string().contains("invalid protocol scheme") => {
Err(anyhow!("{s}: use postgresql:// or grpc://; HTTP management URLs are not valid here"))
}
Err(e) => Err(e),
} Prevention
- Document each config field with the exact scheme it expects
- Reject management/HTTP URLs at config validation for data-plane connstring fields
- Watch for tooling that prefixes tcp:// or ws:// to all addresses
When it happens
Trigger: from_connstring("http://pageserver:6400") or from_connstring("ws://host") — any URL with a scheme other than postgres, postgresql, or grpc, e.g. an accidentally supplied management-HTTP URL where a data-plane connstring was expected.
Common situations: Pasting the pageserver's HTTP management endpoint (http://...:9898) into a field that expects the postgres or grpc data-plane connstring; a wrapper tool that prefixes ws:// or tcp:// to every address; typos like postgress:// or grcp://.
Related errors
- no grpc_url for shard {shard_index}
- no libpq_url for shard {shard_index}
- invalid connstring URL: {err}
- invalid shard URL {url}: must use gRPC
- empty connection string
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/a63245a37a0324e3.
Report an issue: GitHub.