neondatabase/neon · error
found no blocknum in arguments
Error message
found no blocknum in arguments
What it means
After locating the RelTag among multiple arguments, the parser scans from that position onward for the first argument that parses as a BlockNumber (a plain unsigned integer, optionally prefixed blkno=). If none is found, the command bails with this error.
Source
Thrown at pageserver/ctl/src/key.rs:234
.map(|rt| (i, rt))
})
else {
anyhow::bail!("found no RelTag in arguments");
};
let Some(blocknum) = more
.iter()
.map(AsRef::as_ref)
.skip(reltag_at)
.find_map(|s| {
s.split_once("blkno=")
.map(|(_garbage, actual)| actual)
.unwrap_or(s)
.parse::<BlockNumber>()
.ok()
})
else {
anyhow::bail!("found no blocknum in arguments");
};
Ok(KeyMaterial::Split(reltag, blocknum))
}
}
}
}
#[derive(Debug)]
pub(super) struct SpanAttributesFromLogs(RelTag, BlockNumber);
impl std::str::FromStr for SpanAttributesFromLogs {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
// accept the span separator but do not require or fail if either is missing
// "whatever{rel=1663/16389/24615 blkno=1052204 req_lsn=FFFFFFFF/FFFFFFFF}"
let (_, reltag) = sView on GitHub (pinned to 8f60b04da4)
Solutions
- Add the block number as any argument at or after the reltag position, for example 1052204 or blkno=1052204.
- Keep the blkno token after the reltag; arguments before the reltag position are skipped by the scan.
Example fix
# before pageserver_ctl key 1052204 1663/16389/24615 # blocknum search starts at the reltag, finds nothing -> "found no blocknum in arguments" # after pageserver_ctl key 1663/16389/24615 1052204
Defensive patterns
Strategy: validation
Validate before calling
// after the reltag position, at least one argument must parse as a block number
let reltag_at = args.iter().position(|s| s.split_once("rel=").map(|(_, v)| v).unwrap_or(s).parse::<RelTag>().is_ok());
anyhow::ensure!(
reltag_at.is_some_and(|at| args[at..].iter().any(|s| {
s.split_once("blkno=").map(|(_, v)| v).unwrap_or(s).parse::<BlockNumber>().is_ok()
})),
"no block number found after the reltag"
); Type guard
fn has_blocknum_after_reltag(args: &[String]) -> bool {
let at = args.iter().position(|s| s.split_once("rel=").map(|(_, v)| v).unwrap_or(s).parse::<RelTag>().is_ok());
at.is_some_and(|at| args[at..].iter().any(|s| {
s.split_once("blkno=").map(|(_, v)| v).unwrap_or(s).parse::<BlockNumber>().is_ok()
}))
} Prevention
- Order arguments as reltag then block number; the scan ignores arguments before the reltag.
- Keep the blkno= token intact when pasting from logs.
When it happens
Trigger: Arguments contain a valid reltag but no numeric block number after it: blkno written as block=, a non-numeric token, or the block token placed before the reltag (the scan starts at the reltag position).
Common situations: Log formats that drop or rename the blkno= field; assembling arguments by hand in the wrong order.
Related errors
- need 1..N positional arguments describing the key, try hex o
- failed to parse {one:?} as hex or span attributes: - {e1:#}
- found no RelTag in arguments
- cannot find 'rel='
- cannot find 'blkno='
AI-assisted analysis of neondatabase/neon@8f60b04da4 (2026-08-16).
Data as JSON: /api/errors/48fc20e183521ea4.
Report an issue: GitHub.