openai/codex · error · io::Error
memory import requires at least one selected memory
Error message
memory import requires at least one selected memory
What it means
The external-agent memory import returns io::Error(InvalidInput, 'memory import requires at least one selected memory') when the selected_memory slice passed to import() is empty (codex-rs/external-agent-migration/src/memory_import.rs:63-68). Importing external-agent memory (for example Claude Code memory directories) into Codex memories is opt-in per project key; an empty selection is treated as a caller bug rather than a no-op.
Source
Thrown at codex-rs/external-agent-migration/src/memory_import.rs:64
}
#[derive(Serialize)]
struct ProjectScope<'a> {
cwd: &'a Path,
}
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_dbView on GitHub (pinned to 339751715c)
Solutions
- Guard the call: skip import entirely when selected_memory.is_empty()
- Fix the UI so the Import action is disabled until at least one discovered project is selected
- Populate the selection from the discovery result (discover_external_memory_files / projects_needing_import) instead of a hardcoded list
Example fix
// before
let outcome = import(&codex_home, &external_home, state_db, &selected).await?;
// after
if selected.is_empty() {
return Ok(noop_outcome()); // nothing opted in - nothing to import
}
let outcome = import(&codex_home, &external_home, state_db, &selected).await?; Defensive patterns
Strategy: validation
Validate before calling
if selected_memory.is_empty() {
// user opted out - skip the call instead of triggering InvalidInput
return Ok(noop_outcome());
} Try / catch
match err.kind() {
io::ErrorKind::InvalidInput if err.to_string().contains("at least one selected memory") => {
// treat as a selection bug or no-op, not a fatal import failure
}
_ => return Err(err),
} Prevention
- Derive the selection from the discovery scan, never a default empty Vec
- Disable import actions in UI states where the selection is empty
- Treat an empty selection as 'user opted out', not as an import request
When it happens
Trigger: Calling import(codex_home, external_agent_home, state_db, &[]) - a migration wizard invoked with no projects checked, or a programmatic caller forwarding an empty selection list.
Common situations: A UI where 'select none' plus Import is still possible; callers that build the selection by filtering and the filter matches nothing; flows that skip the discovery step and pass a default-empty Vec.
Understand the failure class
Background: Missing required parameter errors: what 'X is required' and 'the required X param is missing' mean, and how to fix them — this error's family across 27 libraries.
Related errors
- memory import requires the Codex state database
- InvalidInput
- only user input can be added to the user-message queue
- queued user input exceeds the maximum length of {MAX_USER_IN
- invalid external agent session import ledger: {err}
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/fd6547e1e6828a9e.
Report an issue: GitHub.