Skip to content

update: shouldRunAutoUpdate silently blocked by future-timestamp stamp file #402

@justrach

Description

@justrach

Problem

update.shouldRunAutoUpdate computes (now_ms - last_check_ms) >= 24h to decide whether to fire. When last_check_ms is in the future relative to now_ms (e.g. NTP rolls the clock backwards, the stamp was written by a host with a faster clock, or someone manually wrote a future stamp), the delta is negative and is always less than 24h, so the gate silently skips the update check for as long as the stamp stays in the future.

For a user whose stamp ends up even one day in the future, codedb mcp will never auto-update for at least a day after the wall clock catches up. Worst case (stamp far in the future) auto-update is permanently dead.

The auto-update commit is be37075 on release/v0.2.5799.

Failing Test

src/tests.zigtest "issue-394: shouldRunAutoUpdate permanently blocked by future-timestamp stamp file":

test "issue-394: shouldRunAutoUpdate permanently blocked by future-timestamp stamp file" {
    const day_ms: i64 = 24 * 60 * 60 * 1000;
    const now_ms: i64 = 1_700_000_000_000;
    const future_last_ms: i64 = now_ms + day_ms * 30; // 30 days in the future

    try testing.expect(update_mod.shouldRunAutoUpdate(now_ms, future_last_ms, false));
}

Currently fails: shouldRunAutoUpdate returns false because (now - last) is -30 * day_ms, which is < 24h.

Branch: issue-394-failing-test.

Expected

A stamp last_check_ms strictly in the future should be treated as invalid — the throttle is a "don't fire too often" guard, not a "never fire when the stamp looks weird" guard. shouldRunAutoUpdate(now, last, false) should return true whenever last > now.

Fix

In src/update.zig:

pub fn shouldRunAutoUpdate(now_ms: i64, last_check_ms: ?i64, env_disabled: bool) bool {
    if (env_disabled) return false;
    const last = last_check_ms orelse return true;
    if (last > now_ms) return true;          // future / skewed stamp → run
    return (now_ms - last) >= auto_update_throttle_ms;
}

Also worth considering: clamp last_ms reads to a sane window (> 0 and within ±10 years of now_ms) and reject otherwise.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingpriority:p2Medium priority

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions