Pumpkin-MC/Pumpkin · warning · TelemetryVerificationError
Timestamp drift exceeded: drift was
Error message
Timestamp drift exceeded: drift was {drift}s (max allowed is {MAX_CLOCK_DRIFT_SECS}s) What it means
TelemetryVerificationError::ClockDriftExceeded { drift } is returned during telemetry signature verification when the request's timestamp is valid but differs from the server's current time by more than MAX_CLOCK_DRIFT_SECS. The drift value in the error reports the actual observed difference. This replay-protection check rejects stale or future-dated requests even when their signature is otherwise valid.
Solutions
- Enable NTP/time sync on the client and server machines so their clocks agree
- Regenerate and resend the request with a fresh timestamp instead of retrying a stale signed request
- If offline buffering is intentional, flush telemetry before it exceeds the MAX_CLOCK_DRIFT_SECS window
- Reduce clock skew in containers by syncing the host clock and avoiding paused VMs/snapshots with stale time
Example fix
// before let ts = cached_timestamp; // minutes old, signature reuse // after let ts = Utc::now(); // re-sign with fresh timestamp before sending let sig = sign_request(&key, &body, &ts);
Defensive patterns
Strategy: retry
Validate before calling
fn drift_ok(sent_at: chrono::DateTime<Utc>, max: u64) -> bool {
(Utc::now() - sent_at).num_seconds().unsigned_abs() <= max
}
// call before signing: assert!(drift_ok(now, MAX_CLOCK_DRIFT_SECS)) Try / catch
match verify_signature(&req) {
Err(TelemetryVerificationError::ClockDriftExceeded { drift }) => {
info!("request drifted {drift}s; asking client to re-sign with fresh timestamp");
retry_with_fresh_timestamp();
}
other => other?,
} Prevention
- Run NTP time sync on all machines producing telemetry
- Re-sign and resend with a fresh timestamp rather than retrying stale signed payloads
- Flush buffered telemetry before it exceeds the allowed drift window
- Keep container/VM hosts' clocks synchronized with the host machine
When it happens
Trigger: A signed telemetry request arrives with a timestamp older/newer than the allowed window: the client machine's clock is skewed, a request was queued/retried past the window, or a captured request is replayed later.
Common situations: Servers or clients with unsynchronized clocks (no NTP); long network queues or offline buffering of telemetry that is sent too late; container hosts whose clocks drift; deliberate replay attempts.
Understand the failure class
Background: Request timed out: what client-side request timeouts mean across libraries (Request timed out, TIMED_OUT, APITimeoutError) — this error's family across 39 libraries.
Related errors
- Invalid timestamp string format
- Failed to verify Ed25519 signature
- Vine timestamp expired or desynchronized: skew of
- Vine challenge nonce mismatch
- Invalid public key hex encoding
AI-assisted analysis of Pumpkin-MC/Pumpkin@8d4639e25a (2026-09-09).
Data as JSON: /api/errors/140dc71c30e239d4.
Report an issue: GitHub.
Appendix: source
Thrown at crates/pumpkin/src/telemetry.rs:123
#[must_use]
pub fn sign_telemetry_payload(
signing_key: &SigningKey,
timestamp_str: &str,
body_bytes: &[u8],
) -> (String, String) {
let signed_data = compute_signed_data(timestamp_str, body_bytes);
let signature = signing_key.sign(&signed_data);
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.View on GitHub (pinned to 8d4639e25a)