astrid-runtime/astrid · error
is not a 64-char hex public key
Error message
{} is not a 64-char hex public key What it means
`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.
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.
Example fix
// before (file content) MCowBQYDK2VwAyEA... # base64 // after 0f1e2d3c4b5a69788796a5b4c3d2e1f00f1e2d3c4b5a69788796a5b4c3d2e1f0
Defensive patterns
Strategy: validation
Validate before calling
HEX=$(tr -d '[:space:]' < "$KEYDIR/$NAME.pub.hex"); [[ $HEX =~ ^[0-9a-fA-F]{64}$ ]] || echo "corrupt public key for $NAME" >&2 Prevention
- 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)
When it happens
Trigger: 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.
Common situations: 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.
Understand the failure class
Background: "Invalid ... format", "must be in format X", "does not look like a ..." — invalid argument format errors across CLI tools and libraries — this error's family across 17 libraries.
Related errors
- InvalidData
- keypair name must not be empty
- source digest must be 64 lowercase hex characters
- a corpus produced no chunks
- a representation record must cover at least one logical…
AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09).
Data as JSON: /api/errors/1cec412c7e285e69.
Report an issue: GitHub.
Appendix: source
Thrown at crates/astrid-cli/src/commands/keypair.rs:464
let text = toml::to_string_pretty(meta).context("serialise keypair meta")?;
let tmp = path.with_extension(format!("{}.tmp", std::process::id()));
fs::write(&tmp, text.as_bytes())?;
#[cfg(unix)]
{
use std::os::unix::fs::PermissionsExt;
fs::set_permissions(&tmp, fs::Permissions::from_mode(0o600))?;
}
fs::rename(&tmp, path).inspect_err(|_| {
let _ = fs::remove_file(&tmp);
})?;
Ok(())
}
fn read_public(path: &Path) -> Result<String> {
let raw = fs::read_to_string(path).with_context(|| format!("read {}", path.display()))?;
let trimmed = raw.trim().to_string();
if trimmed.len() != 64 || !trimmed.chars().all(|c| c.is_ascii_hexdigit()) {
bail!("{} is not a 64-char hex public key", path.display());
}
Ok(trimmed)
}
fn read_meta(paths: &KeyPaths) -> Result<KeyMeta> {
let text = fs::read_to_string(&paths.meta)
.with_context(|| format!("read {}", paths.meta.display()))?;
let meta: KeyMeta =
toml::from_str(&text).with_context(|| format!("parse {}", paths.meta.display()))?;
if meta.schema_version > META_SCHEMA_VERSION {
bail!(
"keypair {} was written by a newer astrid (schema {} > {})",
paths.meta.display(),
meta.schema_version,
META_SCHEMA_VERSION
);
}
if meta.schema_version < META_SCHEMA_VERSION {View on GitHub (pinned to affd8760f4)