openai/codex · error · anyhow::Error

timed out waiting for a client to subscribe to the thread af

Error message

timed out waiting for a client to subscribe to the thread after {}s

What it means

The memory summary artifact carries a format marker: memory_summary.md's first line must be exactly 'v1'. validate_consolidation_artifacts fails when the file is missing (surfaced as the 'read memory summary artifact' context error) or when the first line differs (codex-rs/memories/write/src/workspace.rs:75) — an empty file, prose without the header, or a version written by mismatched tooling.

Source

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

                }
            }
        })
    }
}

async fn request_current_time(
    outgoing: Arc<OutgoingMessageSender>,
    thread_state_manager: ThreadStateManager,
    thread_id: ThreadId,
) -> Result<DateTime<Utc>> {
    let deadline = Instant::now() + CURRENT_TIME_REQUEST_TIMEOUT;
    timeout_at(
        deadline,
        thread_state_manager.wait_for_thread_subscriber(thread_id),
    )
    .await
    .map_err(|_| {
        anyhow!(
            "timed out waiting for a client to subscribe to the thread after {}s",
            CURRENT_TIME_REQUEST_TIMEOUT.as_secs()
        )
    })?;
    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;

View on GitHub (pinned to 339751715c)

Solutions

  1. If the content is v1-format, make the first line exactly 'v1' — no leading blank line, BOM, or whitespace.
  2. Prefer regenerating it by re-running consolidation.
  3. Keep all machines touching a shared memories dir on compatible codex versions.

Example fix

# before (memory_summary.md)
Recap of recent work...
# after
v1
Recap of recent work...
Defensive patterns

Strategy: validation

Validate before calling

async fn summary_has_v1_header(root: &std::path::Path) -> bool {
    tokio::fs::read_to_string(root.join("memory_summary.md"))
        .await
        .ok()
        .and_then(|s| s.lines().next().map(|l| l == "v1"))
        .unwrap_or(false)
}

Try / catch

if let Err(e) = validate_consolidation_artifacts(root).await {
    if e.to_string().contains("does not start with v1") {
        // repair: first line must be exactly 'v1', or regenerate via consolidation
    }
}

Prevention

When it happens

Trigger: Post-consolidation validation reading memory_summary.md whose first line is not exactly 'v1': hand-edited summaries, truncated writes, or version skew between the writer and validator.

Common situations: Editing memory_summary.md manually and dropping the header; codex versions mixed across machines sharing a memories dir; interrupted consolidation leaving a partial file.

Understand the failure class

Related errors


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