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) = s

View on GitHub (pinned to 8f60b04da4)

Solutions

  1. Add the block number as any argument at or after the reltag position, for example 1052204 or blkno=1052204.
  2. 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

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


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