FuelLabs/fuel-core · error

Timestamp not accessible

Error message

Timestamp not accessible

What it means

The compression crate stores repeated values (AssetId, ContractId, Address, PredicateCode, ScriptCode) in a temporal registry keyed by RegistryKey with a registration timestamp. During decompression of a value for an older block, decompress_with checks ctx.config.is_timestamp_accessible(ctx.timestamp, key_timestamp): if more time has passed since the key was registered than Config::temporal_registry_retention, the entry is considered stale and must not be used, so decompression bails. The registry is intentionally write-once/expiring; old keys are expected to be garbage-collected.

Source

Thrown at crates/compression/src/decompress.rs:181

}

macro_rules! decompress_impl {
    ($($type:ty),*) => { paste::paste! {
        $(
            impl<D> DecompressibleBy<DecompressCtx<D>> for $type
            where
                D: TemporalRegistry<$type>
            {
                async fn decompress_with(
                    key: RegistryKey,
                    ctx: &DecompressCtx<D>,
                ) -> anyhow::Result<Self> {
                    if key == RegistryKey::DEFAULT_VALUE {
                        return Ok(<$type>::default());
                    }
                    let key_timestamp = ctx.db.read_timestamp(&key)?;
                    if !ctx.config.is_timestamp_accessible(ctx.timestamp, key_timestamp)? {
                        anyhow::bail!("Timestamp not accessible");
                    }
                    ctx.db.read_registry(&key)
                }
            }
        )*
    }};
}

decompress_impl!(AssetId, ContractId, Address, PredicateCode, ScriptCode);

impl<D, Specification> DecompressibleBy<DecompressCtx<D>> for Coin<Specification>
where
    D: DecompressDb,
    Specification: CoinSpecification,
    Specification::Predicate: DecompressibleBy<DecompressCtx<D>>,
    Specification::PredicateData: DecompressibleBy<DecompressCtx<D>>,
    Specification::PredicateGasUsed: DecompressibleBy<DecompressCtx<D>>,
    Specification::Witness: DecompressibleBy<DecompressCtx<D>>,

View on GitHub (pinned to b9d4d170da)

Solutions

  1. Only decompress blocks whose timestamp is within temporal_registry_retention of when the values were registered; obtain the data from a fresher source instead.
  2. Increase temporal_registry_retention in the compression Config before registering/compressing, then re-sync so entries live long enough for your historical access pattern.
  3. Re-register (re-compress) the value so a fresh RegistryKey/timestamp is produced, then decompress using the new key.
  4. Verify the block timestamps (Tai64) are sane and ordered; an inverted timestamp produces a related 'Invalid timestamp ordering' error from the same check.

Example fix

// before
let registry_retention = Duration::from_secs(60 * 60); // 1h, old blocks fail to decompress

// after
// keep registry entries valid long enough for your historical block access
let registry_retention = Duration::from_secs(60 * 60 * 24 * 30); // 30d
let config = fuel_core_compression::config::Config {
    temporal_registry_retention: registry_retention,
};
Defensive patterns

Strategy: validation

Validate before calling

// Before decompressing historical data, check the value is still inside the retention window.
let age = Tai64N(block_timestamp, 0)
    .duration_since(&Tai64N(key_timestamp, 0))
    .ok_or_else(|| anyhow::anyhow!("key timestamp after block timestamp"))?;
if age > compression_config.temporal_registry_retention {
    anyhow::bail!("registry key expired; re-register the value instead of decompressing");
}
let value = ctx.db.read_registry(&key)?;

Try / catch

// Rust: treat as a non-retryable data-availability failure.
match key.decompress_with(key, &ctx).await {
    Ok(v) => Ok(v),
    Err(e) if e.to_string().contains("Timestamp not accessible") => {
        // value expired from the temporal registry: re-register it, do not retry blindly
        re_register_and_retry(key, ctx).await
    }
    Err(e) => Err(e),
}

Prevention

When it happens

Trigger: Decompressing a RegistryKey whose registration timestamp is older than temporal_registry_retention relative to the block timestamp being processed (e.g., serving or replaying compressed historical blocks after a long gap, or with a short retention configured).

Common situations: temporal_registry_retention tuned down between node restarts; long node downtime followed by replay/backfill of old compressed blocks; querying historical compressed state whose registry entries have expired; clock/Tai64 timestamp anomalies making duration_since compute a too-large value.

Related errors


AI-assisted analysis of FuelLabs/fuel-core@b9d4d170da (2026-08-16). Data as JSON: /api/errors/801fbe77813f6c65. Report an issue: GitHub.