neondatabase/neon · error
invalid specifier '{first}'
Error message
invalid specifier '{first}' What it means
ImageCompressionAlgorithm::from_str parses the pageserver's image compression setting by splitting the string on '(' and ')'. The first component must be 'disabled' or 'zstd'; 'zstd' may carry one parenthesized level component parsed as i8 ('zstd(9)'). Any other first component (empty string aside, which has its own error) raises this 'invalid specifier' bail. Used for the image_compression pageserver configuration.
Source
Thrown at libs/pageserver_api/src/models.rs:1204
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let mut components = s.split(['(', ')']);
let first = components
.next()
.ok_or_else(|| anyhow::anyhow!("empty string"))?;
match first {
"disabled" => Ok(ImageCompressionAlgorithm::Disabled),
"zstd" => {
let level = if let Some(v) = components.next() {
let v: i8 = v.parse()?;
Some(v)
} else {
None
};
Ok(ImageCompressionAlgorithm::Zstd { level })
}
_ => anyhow::bail!("invalid specifier '{first}'"),
}
}
}
impl Display for ImageCompressionAlgorithm {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
ImageCompressionAlgorithm::Disabled => write!(f, "disabled"),
ImageCompressionAlgorithm::Zstd { level } => {
if let Some(level) = level {
write!(f, "zstd({level})")
} else {
write!(f, "zstd")
}
}
}
}
}View on GitHub (pinned to 8f60b04da4)
Solutions
- Use 'disabled' for no compression, plain 'zstd' for the default level
- Specify a level in parentheses: 'zstd(9)'; negative levels are allowed since the field is i8
- Remove separators other than parentheses; 'zstd-9' and 'zstd:9' are invalid
- Check the Display impl round-trip: a value printed by the API is always re-parseable
Example fix
# before (pageserver.toml) image_compression = 'zstd-9' # -> invalid specifier 'zstd-9' # after image_compression = 'zstd(9)'
Defensive patterns
Strategy: type-guard
Validate before calling
fn validate_image_compression(s: &str) -> Result<(), String> {
ImageCompressionAlgorithm::from_str(s)
.map(|_| ())
.map_err(|e| format!("bad image_compression {s:?}: {e:#}; use 'disabled', 'zstd', or 'zstd(<i8>)'"))
} Type guard
/// Mirrors ImageCompressionAlgorithm::from_str without panicking.
fn is_valid_image_compression(s: &str) -> bool {
let mut parts = s.split(['(', ')']);
match parts.next() {
Some("disabled") => true,
Some("zstd") => match parts.next() {
None => true, // plain "zstd"
Some(lvl) => lvl.parse::<i8>().is_ok(),
},
_ => false,
}
} Try / catch
match ImageCompressionAlgorithm::from_str(&value) {
Ok(a) => a,
Err(e) if e.to_string().contains("invalid specifier") => {
return Err(anyhow::anyhow!(
"{e}; accepted specifiers: 'disabled', 'zstd', 'zstd(<i8 level>)' (e.g. 'zstd(9)')"
));
}
Err(e) => return Err(e), // level parse failure, e.g. zstd(300) overflowing i8
} Prevention
- Copy-paste values from the API's own Display output (always round-trippable) instead of inventing syntax
- Validate configuration files in a pre-deploy step by calling FromStr on every enum-like setting
- Reject hyphen/colon level syntax ('zstd-9', 'zstd:9') in docs examples -- only parentheses are valid
- Remember levels are i8: negative allowed, values beyond -128..127 fail parsing
When it happens
Trigger: Setting image_compression in pageserver.toml or the HTTP config API to an unsupported algorithm or syntax: 'zstd-9', 'lz4', 'zstd:9', 'Zstd(9)', or 'zstd[' -- the first split component is not 'disabled' or 'zstd'. (A bad level, e.g. 'zstd(300)' or 'zstd(abc)', instead surfaces the i8 parse error.)
Common situations: Porting settings written for a different compression library's syntax (hyphen or colon separators); assuming old/new format strings like 'zstd9' work; typos and casing differences; docs examples that predate the parser.
Related errors
- pageserver connection information should be provided
- shard {shard_index} missing from pageserver_connection_info
- must have at least one pageserver
- Unknown scheduling policy '{s}', try active,pause,decomissio
- no shards provided
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/cb19f1bac3a1e9ac.
Report an issue: GitHub.