ultraworkers/claw-code · critical

time should be after epoch

Error message

time should be after epoch

What it means

This is a panic, not an error value: unix_time_ms() (plugins/lib.rs:2306) calls SystemTime::now().duration_since(UNIX_EPOCH).expect(...), which unwinds when the system clock reads a time before 1970-01-01 UTC (duration_since returns Err). It is stamped into plugin install records, so any PluginManager install/update path that reaches unix_time_ms() aborts the operation and typically the thread.

Source

Thrown at rust/crates/plugins/src/lib.rs:2309

        .chars()
        .map(|ch| match ch {
            '/' | '\\' | '@' | ':' => '-',
            other => other,
        })
        .collect()
}

fn describe_install_source(source: &PluginInstallSource) -> String {
    match source {
        PluginInstallSource::LocalPath { path } => path.display().to_string(),
        PluginInstallSource::GitUrl { url } => url.clone(),
    }
}

fn unix_time_ms() -> u128 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .expect("time should be after epoch")
        .as_millis()
}

fn copy_dir_all(source: &Path, destination: &Path) -> Result<(), PluginError> {
    fs::create_dir_all(destination)?;
    for entry in fs::read_dir(source)? {
        let entry = entry?;
        let target = destination.join(entry.file_name());
        if entry.file_type()?.is_dir() {
            copy_dir_all(&entry.path(), &target)?;
        } else {
            fs::copy(entry.path(), target)?;
        }
    }
    Ok(())
}

fn update_settings_json(

View on GitHub (pinned to 08106b0c37)

Solutions

  1. Fix the clock before running plugin operations: enable NTP/systemd-timesyncd (timedatectl set-ntp true) or set the date manually: date -s '2026-08-17 12:00:00'
  2. On VMs, restore from a snapshot that had time sync enabled, or restart with clock synchronization (Hyper-V/KVM time sync flag on)
  3. Remove faketime/LD_PRELOAD skew for processes that install plugins, or point it to a post-1970 time
  4. As a library fix, replace expect with a safe floor: UNIX_EPOCH.checked_sub_backwards-style handling, e.g. SystemTime::now().duration_since(UNIX_EPOCH).map(|d| d.as_millis()).unwrap_or(0)

Example fix

// before (plugins/src/lib.rs:2306) — panics pre-epoch
fn unix_time_ms() -> u128 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .expect("time should be after epoch")
        .as_millis()
}

// after — clamp instead of panic; a wrong timestamp is better than a crashed install
fn unix_time_ms() -> u128 {
    SystemTime::now()
        .duration_since(UNIX_EPOCH)
        .map(|d| d.as_millis())
        .unwrap_or(0)
}
Defensive patterns

Strategy: validation

Validate before calling

fn clock_after_epoch() -> bool {
    std::time::SystemTime::now()
        .duration_since(std::time::UNIX_EPOCH)
        .is_ok()
}

// gate plugin install/update on a sane clock
if !clock_after_epoch() {
    return Err("system clock is before 1970; run NTP sync before installing plugins".into());
}

Try / catch

// unix_time_ms panics; isolate plugin installs so one bad clock cannot kill the host process
let outcome = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| {
    manager.install(source)
}));
match outcome {
    Ok(res) => res?,
    Err(_) => Err(PluginError::Other("install panicked (check system clock)".into())),
}

Prevention

When it happens

Trigger: PluginManager::install / update (or any code path calling unix_time_ms() to timestamp InstalledPluginRecord) running on a machine whose RTC is set before the epoch: fresh boards with dead CMOS batteries reading 1970/1969, VMs restored from snapshots with regressed clocks, containers pinned via clock namespaces or faketime to negative offsets.

Common situations: Embedded devices and Raspberry Pis booting with 1969/1970 clocks before NTP sync; VMs after host hibernate/restore where the guest clock lands pre-epoch; CI with faketime or libfaketime LD_PRELOAD set to a negative offset; deliberately skewed clocks for certificate tests.

Related errors


AI-assisted analysis of ultraworkers/claw-code@08106b0c37 (2026-08-18). Data as JSON: /api/errors/f03484c3acbf87fb. Report an issue: GitHub.