{"record":{"id":"2ebdad815c33f178","repo":"neondatabase/neon","slug":"failed-to-parse-one-as-hex-or-span-attributes","errorCode":null,"errorMessage":"failed to parse {one:?} as hex or span attributes:\n- {e1:#}\n- {e2:#}","messagePattern":"failed to parse (.+?) as hex or span attributes:\n- (.+?)\n- (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pageserver/ctl/src/key.rs","lineNumber":196,"sourceCode":"impl<S: AsRef<str>> TryFrom<&[S]> for KeyMaterial {\n    type Error = anyhow::Error;\n\n    fn try_from(value: &[S]) -> Result<Self, Self::Error> {\n        match value {\n            [] => anyhow::bail!(\n                \"need 1..N positional arguments describing the key, try hex or a log line\"\n            ),\n            [one] => {\n                let one = one.as_ref();\n\n                let key = Key::from_hex(one).map(KeyMaterial::Hex);\n\n                let attrs = SpanAttributesFromLogs::from_str(one).map(KeyMaterial::String);\n\n                match (key, attrs) {\n                    (Ok(key), _) => Ok(key),\n                    (_, Ok(s)) => Ok(s),\n                    (Err(e1), Err(e2)) => anyhow::bail!(\n                        \"failed to parse {one:?} as hex or span attributes:\\n- {e1:#}\\n- {e2:#}\"\n                    ),\n                }\n            }\n            more => {\n                // assume going left to right one of these is a reltag and then we find a blocknum\n                // this works, because we don't have plain numbers at least right after reltag in\n                // logs. for some definition of \"works\".\n\n                let Some((reltag_at, reltag)) = more\n                    .iter()\n                    .map(AsRef::as_ref)\n                    .enumerate()\n                    .find_map(|(i, s)| {\n                        s.split_once(\"rel=\")\n                            .map(|(_garbage, actual)| actual)\n                            .unwrap_or(s)\n                            .parse::<RelTag>()","sourceCodeStart":178,"sourceCodeEnd":214,"githubUrl":"https://github.com/neondatabase/neon/blob/8f60b04da47ffefe0e52bda2440134b42874eb75/pageserver/ctl/src/key.rs#L178-L214","documentation":"With a single positional argument, the key subcommand tries two parsers in order: Key::from_hex (the fixed-width hexadecimal form of a key) and SpanAttributesFromLogs::from_str (a pasted log line containing rel= and blkno=). If both fail, this combined error reports both parse causes so you can see why neither form matched.","triggerScenarios":"One argument that is neither a valid full-length hex key nor a log line with parseable rel= and blkno= fields; for example a truncated hex string, or a log line missing blkno.","commonSituations":"Copying only a prefix of a key from logs; pasting a log line whose rel= value is malformed; extra shell quoting that mangles the argument.","solutions":["Read both causes in the message: the first explains the hex failure, the second the log-line failure; fix whichever form you intended.","For hex, paste the complete key string exactly as the pageserver prints it, not a prefix.","For log lines, ensure both rel= and blkno= markers are present and their values well-formed."],"exampleFix":"# before\npageserver_ctl key \"000000067F00010001\"\n# -> failed to parse ... as hex or span attributes (both errors listed)\n\n# after\npageserver_ctl key \"000000067F000100010000AC0000000006\"\n# or paste the whole log line:\n# pageserver_ctl key \"whatever{rel=1663/16389/24615 blkno=1052204 req_lsn=FFFFFFFF/FFFFFFFF}\"","handlingStrategy":"validation","validationCode":"// try the cheap, unambiguous forms first before relying on the ctl's combined parse\nif let Ok(key) = Key::from_hex(arg) {\n    // unambiguous hex form\n} else if arg.contains(\"rel=\") && arg.contains(\"blkno=\") {\n    // log-line form; let the ctl parse it\n} else {\n    anyhow::bail!(\"argument is neither a hex key nor a log line with rel=/blkno=\");\n}","typeGuard":"fn looks_like_key_material(s: &str) -> bool {\n    Key::from_hex(s).is_ok() || (s.contains(\"rel=\") && s.contains(\"blkno=\"))\n}","tryCatchPattern":null,"preventionTips":["Paste keys exactly as printed by the pageserver; do not truncate them.","For log lines, verify both rel= and blkno= markers are present before invoking the ctl."],"tags":["rust","neon","ctl","key-parsing","hex"],"backgroundTag":"invalid-key-format","analyzedSha":"8f60b04da47ffefe0e52bda2440134b42874eb75","analyzedAt":"2026-08-16T23:39:28.135Z","schemaVersion":2},"datasetVersion":"2026-08-17T04:17:16.089Z"}