neondatabase/neon · error

found no RelTag in arguments

Error message

found no RelTag in arguments

What it means

With two or more positional arguments, the key subcommand scans left to right for the first argument that parses as a RelTag (after stripping an optional rel= prefix). A RelTag looks like 1663/16389/24615 (tablespace/OID/database, optionally with a fork number). If no argument parses as a RelTag, the command bails.

Source

Thrown at pageserver/ctl/src/key.rs:219

            more => {
                // assume going left to right one of these is a reltag and then we find a blocknum
                // this works, because we don't have plain numbers at least right after reltag in
                // logs. for some definition of "works".

                let Some((reltag_at, reltag)) = more
                    .iter()
                    .map(AsRef::as_ref)
                    .enumerate()
                    .find_map(|(i, s)| {
                        s.split_once("rel=")
                            .map(|(_garbage, actual)| actual)
                            .unwrap_or(s)
                            .parse::<RelTag>()
                            .ok()
                            .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))

View on GitHub (pinned to 8f60b04da4)

Solutions

  1. Include the reltag as one argument, for example 1663/16389/24615 or rel=1663/16389/24615.
  2. When copy-pasting from logs, keep the rel=... token intact; the parser strips the prefix itself.

Example fix

# before
pageserver_ctl key 1052204 FFFF/FFFFFFFF
# -> "found no RelTag in arguments"

# after
pageserver_ctl key 1663/16389/24615 1052204
Defensive patterns

Strategy: validation

Validate before calling

// ensure at least one argument parses as a RelTag (with optional rel= prefix)
let has_reltag = args.iter().any(|s| {
    s.split_once("rel=").map(|(_, v)| v).unwrap_or(s).parse::<RelTag>().is_ok()
});
anyhow::ensure!(has_reltag, "no argument parses as a RelTag like 1663/16389/24615");

Type guard

fn contains_reltag(args: &[String]) -> bool {
    args.iter().any(|s| {
        s.split_once("rel=").map(|(_, v)| v).unwrap_or(s).parse::<RelTag>().is_ok()
    })
}

Prevention

When it happens

Trigger: Multiple arguments where no element is a valid RelTag: only a block number and an LSN, or a reltag with non-numeric or missing components.

Common situations: Splitting a log line on whitespace and losing the rel= token; reltags with an unexpected fork suffix; hand-typed arguments with typos.

Related errors


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