openai/codex · error · io::Error
memory import requires the Codex state database
Error message
memory import requires the Codex state database
What it means
import() requires a live Codex state database handle and returns io::Error(NotConnected, 'memory import requires the Codex state database') when state_db is None (codex-rs/external-agent-migration/src/memory_import.rs:69-74). After copying memory files into codex_home/memories, the import enqueues a global memory consolidation through the state DB; without the handle there is no way to schedule it, so the call refuses rather than importing untracked files.
Source
Thrown at codex-rs/external-agent-migration/src/memory_import.rs:70
pub(super) async fn import(
codex_home: &Path,
external_agent_home: &Path,
state_db: Option<&StateDbHandle>,
selected_memory: &[String],
) -> io::Result<MemoryImportOutcome> {
let selected_memory = selected_memory
.iter()
.map(String::as_str)
.collect::<BTreeSet<_>>();
if selected_memory.is_empty() {
return Err(io::Error::new(
io::ErrorKind::InvalidInput,
"memory import requires at least one selected memory",
));
}
let state_db = state_db.ok_or_else(|| {
io::Error::new(
io::ErrorKind::NotConnected,
"memory import requires the Codex state database",
)
})?;
let memory_root = codex_home.join("memories");
codex_memories_write::workspace::prepare_memory_workspace(&memory_root)
.await
.map_err(io::Error::other)?;
let memory_files = discover_external_memory_files(external_agent_home)?;
let copy_outcome = copy_resources(codex_home, &memory_files, &selected_memory)?;
if copy_outcome.workspace_changed
&& let Err(err) = state_db
.memories()
.enqueue_global_consolidation(chrono::Utc::now().timestamp())
.await
{
tracing::warn!(error = %err, "failed to enqueue imported memory consolidation");
}View on GitHub (pinned to 339751715c)
Solutions
- Open the Codex state database for the target codex_home and pass Some(&handle) before importing
- If the DB open failed earlier in the flow, propagate that error instead of continuing with None
- In tests, create a StateDbHandle against a temp directory so import runs against real (temporary) state
Example fix
// before let outcome = import(&codex_home, &external_home, None, &selected).await?; // NotConnected // after let state_db = StateDbHandle::open(&codex_home).await?; // or reuse the app's existing handle let outcome = import(&codex_home, &external_home, Some(&state_db), &selected).await?;
Defensive patterns
Strategy: validation
Validate before calling
let Some(state_db) = state_db.as_ref() else {
// open it or fail loudly - import cannot run without it
anyhow::bail!("state database unavailable; cannot import memory");
}; Try / catch
match err.kind() {
io::ErrorKind::NotConnected => { /* open/repair the state DB, then retry import */ }
_ => return Err(err),
} Prevention
- Open the state DB once at startup and thread &StateDbHandle through migration calls
- Never map a failed DB open to None - propagate the error
- ErrorKind::NotConnected here means 'handle not supplied', not a network problem
When it happens
Trigger: Calling import(..., None /* state_db */, ...) - the handle was never opened, an earlier open failure was swallowed, or a test/CLI path forgot to construct the StateDbHandle.
Common situations: Refactors that changed import's signature leaving some caller passing None; migration run in a context where the state DB failed to open (locked, missing permissions, wrong codex_home); unit tests with a temp codex_home but no state DB.
Related errors
- memory import requires at least one selected memory
- InvalidInput
- invalid external agent session import ledger: {err}
- Unsupported platform: ${platform} (${arch})
- Unsupported target triple: ${targetTriple}
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/c2a144a4dab8ace7.
Report an issue: GitHub.