openai/codex · error · anyhow::Error

current-time request was canceled: {err}

Error message

current-time request was canceled: {err}

What it means

append_entry takes the exclusive lock with bounded retries plus RETRY_SLEEP backoff; if another writer holds the lock through the whole window the append fails with ErrorKind::WouldBlock (codex-rs/message-history/src/lib.rs:181). The entry is NOT written when this fires — callers must retry or explicitly drop it; treating the error as success silently loses history.

Source

Thrown at codex-rs/app-server/src/current_time.rs:126

        .send_request_to_connections(
            Some(&connection_ids),
            ServerRequestPayload::CurrentTimeRead(CurrentTimeReadParams {
                thread_id: thread_id.to_string(),
            }),
            /*thread_id*/ None,
        )
        .await;

    let result = match timeout_at(deadline, rx).await {
        Ok(Ok(Ok(result))) => result,
        Ok(Ok(Err(err))) => {
            bail!(
                "current-time request failed: code={} message={}",
                err.code,
                err.message
            );
        }
        Ok(Err(err)) => bail!("current-time request was canceled: {err}"),
        Err(_) => {
            let _canceled = outgoing.cancel_request(&request_id).await;
            bail!(
                "current-time request timed out after {}s",
                CURRENT_TIME_REQUEST_TIMEOUT.as_secs()
            );
        }
    };
    let response: CurrentTimeReadResponse =
        serde_json::from_value(result).context("invalid current-time response")?;

    DateTime::from_timestamp(response.current_time_at, 0)
        .ok_or_else(|| anyhow!("current-time response is outside the supported range"))
}

fn require_single_current_time_connection(connection_ids: &[ConnectionId]) -> Result<ConnectionId> {
    // External clocks are not interchangeable, so do not choose one silently.
    match connection_ids {

View on GitHub (pinned to 339751715c)

Solutions

  1. Retry the append once the contention window passes — the entry is still pending, not persisted.
  2. Enforce a single writer per history file (per user or per session).
  3. Lower the max-bytes cap so in-place trims finish quickly.
  4. Move the history file off network storage.

Example fix

// before
append_entry(&path, entry).await?;
// after: bounded retry on contention
let mut attempt = 0;
loop {
    match append_entry(&path, entry.clone()).await {
        Err(e) if e.kind() == std::io::ErrorKind::WouldBlock && attempt < 5 => {
            attempt += 1;
            tokio::time::sleep(std::time::Duration::from_millis(100 * attempt)).await;
        }
        r => break r?,
    }
}
Defensive patterns

Strategy: retry

Validate before calling

fn single_writer_guard(lock_path: &std::path::Path) -> Option<fs2::File> {
    let f = std::fs::OpenOptions::new()
        .write(true)
        .create(true)
        .open(lock_path)
        .ok()?;
    f.try_lock_exclusive().ok().map(|_| f)
}

Try / catch

let mut attempt = 0;
loop {
    match append_entry(&path, entry.clone()).await {
        Err(e) if e.kind() == std::io::ErrorKind::WouldBlock && attempt < 5 => {
            attempt += 1;
            tokio::time::sleep(std::time::Duration::from_millis(100 * attempt)).await;
        }
        r => break r?, // never swallow: the entry is unwritten on WouldBlock
    }
}

Prevention

When it happens

Trigger: Two processes or threads calling append_entry on the same history file concurrently, with one keeping the lock past the retry budget (large trim under the max_bytes cap, slow or network storage).

Common situations: Parallel codex sessions sharing CODEX_HOME; scripted bulk history writes; history files on network filesystems with slow locking.

Related errors


AI-assisted analysis of openai/codex@339751715c (2026-08-25). Data as JSON: /api/errors/17edf614c5b36c1f. Report an issue: GitHub.