astrid-runtime/astrid · error

signed channel published-at is unreasonably far in the…

Error message

signed channel published-at is unreasonably far in the future

What it means

The pointer's `published_at` must not be more than MAX_FUTURE_SKEW_SECS ahead of the caller's current time. A publication timestamp far in the future indicates a badly generated metadata file or a client clock that is far behind, either of which would break freshness and expiry reasoning, so it is rejected.

Solutions

  1. Sync the local clock via NTP (`timedatectl set-ntp true`) and retry
  2. Check the publishing tool writes `published-at` as UTC RFC 3339 (e.g. `2026-09-09T12:00:00Z`)
  3. Re-generate the channel pointer with a correct timestamp if you produced it
  4. Verify no offset was dropped when serializing chrono DateTime to the TOML

Example fix

// before: naive local time serialized without offset
published-at = "2026-09-09T12:00:00"
// after
published-at = "2026-09-09T12:00:00Z"
Defensive patterns

Strategy: validation

Validate before calling

fn publish_time_is_reasonable(p: &ChannelPointer, now: chrono::DateTime<Utc>) -> bool {
    p.published_at <= now + chrono::Duration::seconds(MAX_FUTURE_SKEW_SECS)
}

Type guard

fn published_not_in_future(p: &ChannelPointer, now: chrono::DateTime<Utc>) -> bool {
    p.published_at <= now + chrono::Duration::seconds(MAX_FUTURE_SKEW_SECS)
}

Try / catch

match parse_channel(&bytes, channel, Utc::now()) {
    Err(e) if e.to_string().contains("unreasonably far in the future") => {
        anyhow::bail!("local clock is likely wrong or metadata timestamp is bad; sync clock and retry")
    }
    other => other?,
}

Prevention

When it happens

Trigger: parse_channel or enforce_continuity sees `published_at > now + MAX_FUTURE_SKEW_SECS`; usually a publisher writing local (non-UTC) time misinterpreted as UTC, or the client's clock set months/years behind.

Common situations: Machine with wrong year/RTC battery dead (clock reset to 2020) making a 2026 publish look absurdly future; publisher script formatting a naive datetime without timezone; fabricated metadata.

Related errors


AI-assisted analysis of astrid-runtime/astrid@affd8760f4 (2026-09-09). Data as JSON: /api/errors/369a0c38e6ff78a0. Report an issue: GitHub.

Appendix: source

Thrown at crates/astrid-cli/src/commands/update_channel.rs:487

    ensure!(
        pointer.channel == expected_channel.as_str(),
        "signed channel names '{}', expected '{}'",
        pointer.channel,
        expected_channel.as_str()
    );
    ensure!(
        pointer.generation > 0,
        "signed channel generation must be positive"
    );
    let published = canonical_time(&pointer.published_at, "published-at")?;
    let expires = canonical_time(&pointer.expires_at, "expires-at")?;
    ensure!(expires > published, "signed channel lifetime is invalid");
    if let Some(now) = now {
        ensure!(now <= expires, "signed channel metadata has expired");
        let latest_reasonable_publication = now
            .checked_add_signed(chrono::Duration::seconds(MAX_FUTURE_SKEW_SECS))
            .context("channel publication skew overflowed the clock")?;
        ensure!(
            published <= latest_reasonable_publication,
            "signed channel published-at is unreasonably far in the future"
        );
    }
    let max_lifetime = match expected_channel {
        UpdateChannel::Stable => chrono::Duration::days(30),
        UpdateChannel::Dev => chrono::Duration::days(7),
        UpdateChannel::Nightly => chrono::Duration::days(2),
    };
    ensure!(
        expires.signed_duration_since(published) <= max_lifetime,
        "signed channel lifetime exceeds the maximum for its channel"
    );
    let version = canonical_version(&pointer.release.version)?;
    let nightly_commit = nightly_source_commit(&version);
    match expected_channel {
        UpdateChannel::Nightly => ensure!(
            nightly_commit.is_some() && version.build.is_empty(),

View on GitHub (pinned to affd8760f4)