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
- Retry the search after the writer finishes — the error is transient by design.
- Reduce the number of concurrent processes sharing the same history file.
- Lower the history max-bytes setting so trims under lock finish quickly.
- 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
- Treat WouldBlock from history APIs as retryable, never as data loss.
- Serialize history access per user/machine — one writer at a time.
- Keep history under the byte cap so locked rewrites finish quickly.
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
- current-time request was canceled: {err}
- mutex poisoned
- WouldBlock
- Unsupported platform: ${platform} (${arch})
- Unsupported target triple: ${targetTriple}
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/d0a45546a3c176da.
Report an issue: GitHub.