Pumpkin-MC/Pumpkin · error · TelemetryVerificationError
Invalid signature hex encoding
Error message
Invalid signature hex encoding
What it means
TelemetryVerificationError::InvalidSignatureHex, produced when the caller-supplied signature cannot be parsed as a hex string. The signature must be hex-encoded (128 hex chars for a 64-byte Ed25519 signature). Thrown before verification runs.
Solutions
- Encode the signature as pure hex (`hex::encode`) on the client side
- Normalize the transport (header/query) so it does not alter the signature string
- Strip whitespace, quotes, and prefixes from the signature before calling verify
Example fix
// before let sig = base64::engine::general_purpose::STANDARD.encode(signature_bytes); // after let sig = hex::encode(signature_bytes);
Defensive patterns
Strategy: validation
Validate before calling
fn is_hex(s: &str) -> bool { !s.is_empty() && s.len() % 2 == 0 && s.bytes().all(|b| b.is_ascii_hexdigit()) }
if !is_hex(sig.trim()) { return Err("signature must be pure hex"); } Type guard
fn valid_signature_hex(s: &str) -> bool {
let t = s.trim().trim_start_matches("0x");
t.len() == 128 && t.bytes().all(|b| b.is_ascii_hexdigit())
} Try / catch
match telemetry::verify(&key, &sig, &msg, now) {
Err(TelemetryVerificationError::InvalidSignatureHex) => log::warn!("client sent non-hex signature; check client encoding"),
Ok(()) => { /* proceed */ }
Err(e) => return Err(e.into()),
} Prevention
- Use hex::encode consistently for signatures across client and server
- Sanitize signature values received via HTTP headers/query (trim, strip prefixes)
- Add an integration test signing and verifying an end-to-end request
When it happens
Trigger: Calling telemetry::verify with a signature string containing non-hex characters, odd length, base64 content, or extra whitespace/prefixes.
Common situations: Client sends the signature base64-encoded while the server expects hex; signature URL-decoded/mangled in transit; signature copied with surrounding quotes or a '0x' prefix.
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
- Invalid public key hex encoding
- Invalid public key bytes
- Invalid signature bytes
- Token not signed by trusted Mojang key
- Invalid signature
AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09).
Data as JSON: /api/errors/85d7c9d637d38759.
Report an issue: GitHub.
Appendix: source
Thrown at crates/pumpkin/src/telemetry.rs:131
let pubkey_hex = hex::encode(signing_key.verifying_key().to_bytes());
let sig_hex = hex::encode(signature.to_bytes());
(pubkey_hex, sig_hex)
}
/// Errors that can occur during telemetry request signature verification.
#[derive(Debug, thiserror::Error, PartialEq, Eq)]
pub enum TelemetryVerificationError {
#[error("Invalid timestamp string format")]
InvalidTimestamp,
#[error(
"Timestamp drift exceeded: drift was {drift}s (max allowed is {MAX_CLOCK_DRIFT_SECS}s)"
)]
ClockDriftExceeded { drift: u64 },
#[error("Invalid public key hex encoding")]
InvalidPublicKeyHex,
#[error("Invalid public key bytes: {0}")]
InvalidPublicKey(String),
#[error("Invalid signature hex encoding")]
InvalidSignatureHex,
#[error("Invalid signature bytes: {0}")]
InvalidSignature(String),
#[error("Signature verification failed: {0}")]
VerificationFailed(String),
}
/// Verifies a signed telemetry request against an Ed25519 public key and timestamp.
///
/// Ensures clock drift between `current_time_secs` and `timestamp_str` does not exceed `±300` seconds.
pub fn verify_telemetry_request(
pubkey_hex: &str,
sig_hex: &str,
timestamp_str: &str,
body_bytes: &[u8],
current_time_secs: u64,
) -> Result<(), TelemetryVerificationError> {
let ts: u64 = timestamp_strView on GitHub (pinned to 8d4639e25a)