{"record":{"id":"48fc20e183521ea4","repo":"neondatabase/neon","slug":"found-no-blocknum-in-arguments","errorCode":null,"errorMessage":"found no blocknum in arguments","messagePattern":"found no blocknum in arguments","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pageserver/ctl/src/key.rs","lineNumber":234,"sourceCode":"                            .map(|rt| (i, rt))\n                    })\n                else {\n                    anyhow::bail!(\"found no RelTag in arguments\");\n                };\n\n                let Some(blocknum) = more\n                    .iter()\n                    .map(AsRef::as_ref)\n                    .skip(reltag_at)\n                    .find_map(|s| {\n                        s.split_once(\"blkno=\")\n                            .map(|(_garbage, actual)| actual)\n                            .unwrap_or(s)\n                            .parse::<BlockNumber>()\n                            .ok()\n                    })\n                else {\n                    anyhow::bail!(\"found no blocknum in arguments\");\n                };\n\n                Ok(KeyMaterial::Split(reltag, blocknum))\n            }\n        }\n    }\n}\n\n#[derive(Debug)]\npub(super) struct SpanAttributesFromLogs(RelTag, BlockNumber);\n\nimpl std::str::FromStr for SpanAttributesFromLogs {\n    type Err = anyhow::Error;\n\n    fn from_str(s: &str) -> Result<Self, Self::Err> {\n        // accept the span separator but do not require or fail if either is missing\n        // \"whatever{rel=1663/16389/24615 blkno=1052204 req_lsn=FFFFFFFF/FFFFFFFF}\"\n        let (_, reltag) = s","sourceCodeStart":216,"sourceCodeEnd":252,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/pageserver/ctl/src/key.rs#L216-L252","documentation":"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.","triggerScenarios":"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).","commonSituations":"Log formats that drop or rename the blkno= field; assembling arguments by hand in the wrong order.","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."],"exampleFix":"# before\npageserver_ctl key 1052204 1663/16389/24615\n# blocknum search starts at the reltag, finds nothing -> \"found no blocknum in arguments\"\n\n# after\npageserver_ctl key 1663/16389/24615 1052204","handlingStrategy":"validation","validationCode":"// after the reltag position, at least one argument must parse as a block number\nlet reltag_at = args.iter().position(|s| s.split_once(\"rel=\").map(|(_, v)| v).unwrap_or(s).parse::<RelTag>().is_ok());\nanyhow::ensure!(\n    reltag_at.is_some_and(|at| args[at..].iter().any(|s| {\n        s.split_once(\"blkno=\").map(|(_, v)| v).unwrap_or(s).parse::<BlockNumber>().is_ok()\n    })),\n    \"no block number found after the reltag\"\n);","typeGuard":"fn has_blocknum_after_reltag(args: &[String]) -> bool {\n    let at = args.iter().position(|s| s.split_once(\"rel=\").map(|(_, v)| v).unwrap_or(s).parse::<RelTag>().is_ok());\n    at.is_some_and(|at| args[at..].iter().any(|s| {\n        s.split_once(\"blkno=\").map(|(_, v)| v).unwrap_or(s).parse::<BlockNumber>().is_ok()\n    }))\n}","tryCatchPattern":null,"preventionTips":["Order arguments as reltag then block number; the scan ignores arguments before the reltag.","Keep the blkno= token intact when pasting from logs."],"tags":["rust","neon","ctl","key-parsing","blocknum"],"backgroundTag":"blocknum-parse-failed","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}