{"record":{"id":"1cec412c7e285e69","repo":"astrid-runtime/astrid","slug":"is-not-a-64-char-hex-public-key","errorCode":null,"errorMessage":"{} is not a 64-char hex public key","messagePattern":"(.+?) is not a 64-char hex public key","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/astrid-cli/src/commands/keypair.rs","lineNumber":464,"sourceCode":"    let text = toml::to_string_pretty(meta).context(\"serialise keypair meta\")?;\n    let tmp = path.with_extension(format!(\"{}.tmp\", std::process::id()));\n    fs::write(&tmp, text.as_bytes())?;\n    #[cfg(unix)]\n    {\n        use std::os::unix::fs::PermissionsExt;\n        fs::set_permissions(&tmp, fs::Permissions::from_mode(0o600))?;\n    }\n    fs::rename(&tmp, path).inspect_err(|_| {\n        let _ = fs::remove_file(&tmp);\n    })?;\n    Ok(())\n}\n\nfn read_public(path: &Path) -> Result<String> {\n    let raw = fs::read_to_string(path).with_context(|| format!(\"read {}\", path.display()))?;\n    let trimmed = raw.trim().to_string();\n    if trimmed.len() != 64 || !trimmed.chars().all(|c| c.is_ascii_hexdigit()) {\n        bail!(\"{} is not a 64-char hex public key\", path.display());\n    }\n    Ok(trimmed)\n}\n\nfn read_meta(paths: &KeyPaths) -> Result<KeyMeta> {\n    let text = fs::read_to_string(&paths.meta)\n        .with_context(|| format!(\"read {}\", paths.meta.display()))?;\n    let meta: KeyMeta =\n        toml::from_str(&text).with_context(|| format!(\"parse {}\", paths.meta.display()))?;\n    if meta.schema_version > META_SCHEMA_VERSION {\n        bail!(\n            \"keypair {} was written by a newer astrid (schema {} > {})\",\n            paths.meta.display(),\n            meta.schema_version,\n            META_SCHEMA_VERSION\n        );\n    }\n    if meta.schema_version < META_SCHEMA_VERSION {","sourceCodeStart":446,"sourceCodeEnd":482,"githubUrl":"https://github.com/astrid-runtime/astrid/blob/affd8760f44190dbdfbec23403f4c4b642c33112/crates/astrid-cli/src/commands/keypair.rs#L446-L482","documentation":"`read_public` loads a keypair's public-key file and requires its trimmed contents to be exactly 64 ASCII hex characters (a 32-byte ed25519 public key). Any other content — empty, truncated, base64, or with stray characters — bails with the path named in the message.","triggerScenarios":"The .pub.hex file is empty, truncated, contains base64 instead of hex, has extra whitespace/newlines beyond trim, or was overwritten by another tool; also hit whenever load_public_key_hex resolves --keypair for invite redeem.","commonSituations":"Interrupted write during keypair generation; manual copy-paste of the key introduced formatting; editor or sync tool mangled the file; version/tooling that wrote a different encoding.","solutions":["Inspect the file named in the error and restore the correct 64-char hex public key.","Re-derive it if possible (e.g. from the private key) or regenerate the keypair with `astrid keypair generate <name> --force`.","Re-run with --public-key <hex> inline instead of --keypair if you have the key elsewhere.","Ensure whatever writes the file emits lowercase/uppercase hex only, no prefixes."],"exampleFix":"// before (file content)\nMCowBQYDK2VwAyEA...   # base64\n// after\n0f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0","handlingStrategy":"validation","validationCode":"HEX=$(tr -d '[:space:]' < \"$KEYDIR/$NAME.pub.hex\"); [[ $HEX =~ ^[0-9a-fA-F]{64}$ ]] || echo \"corrupt public key for $NAME\" >&2","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Validate pub hex files after generation in provisioning","Never hand-edit key files; regenerate instead","Ensure only astrid writes to the key directory (no sync tools)"],"tags":["keypair","validation","hex"],"backgroundTag":"invalid-argument-format","analyzedSha":"affd8760f44190dbdfbec23403f4c4b642c33112","analyzedAt":"2026-09-09T21:28:12.402Z","contentChangedAt":"2026-09-09T21:28:12.402Z","schemaVersion":2},"datasetVersion":"2026-09-17T15:17:12.973Z"}