openai/codex · error · anyhow::Error

current-time request failed: code={} message={}

Error message

current-time request failed: code={} message={}

What it means

History reads take a shared lock with try_lock_shared, sleeping RETRY_SLEEP between attempts; when every attempt hits WouldBlock — a writer has held the exclusive lock for the entire window — lookup_batch gives up with ErrorKind::WouldBlock (codex-rs/message-history/src/batch.rs:131). This is a contention signal, not corruption: the file is fine, another process is writing to it for too long.

Source

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

    let connection_ids = thread_state_manager
        .subscribed_connection_ids(thread_id)
        .await;
    let connection_id = require_single_current_time_connection(&connection_ids)?;
    let connection_ids = [connection_id];
    let (request_id, rx) = outgoing
        .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)

View on GitHub (pinned to 339751715c)

Solutions

  1. Retry the search after the writer finishes — the error is transient by design.
  2. Reduce the number of concurrent processes sharing the same history file.
  3. Lower the history max-bytes setting so trims under lock finish quickly.
  4. If persistent, check for a stuck process holding the lock (lsof on the history and lock files).

Example fix

// before
let batch = lookup_batch(&mut file, cursor, &config)?;
// after: treat WouldBlock as transient contention
let batch = match lookup_batch(&mut file, cursor, &config) {
    Err(e) if e.kind() == std::io::ErrorKind::WouldBlock => {
        std::thread::sleep(std::time::Duration::from_millis(250));
        lookup_batch(&mut file, cursor, &config)?
    }
    r => r?,
};
Defensive patterns

Strategy: retry

Validate before calling

use fs2::FileExt;

fn history_lock_free(path: &std::path::Path) -> bool {
    match std::fs::File::open(path) {
        Ok(f) => f.try_lock_exclusive().is_ok(),
        Err(_) => false,
    }
}

Try / catch

let mut attempt = 0;
loop {
    match lookup_batch(&mut file, cursor, &config) {
        Err(e) if e.kind() == std::io::ErrorKind::WouldBlock && attempt < 5 => {
            attempt += 1;
            std::thread::sleep(RETRY_SLEEP * attempt as u32);
        }
        r => break r?,
    }
}

Prevention

When it happens

Trigger: search_batch / batch_for reads colliding with a long append/trim: append_entry holds the exclusive lock while rewriting a max_bytes-capped history file, so readers starve for the whole retry window.

Common situations: Multiple codex processes sharing one history file under the same CODEX_HOME; history grown to the byte cap so every append rewrites the whole file under lock; slow disks stretching lock hold time.

Related errors


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