openai/codex · error · MemoriesBackendError

I/O error while reading memories: {0}

Error message

I/O error while reading memories: {0}

What it means

The catch-all I/O variant of MemoriesBackendError, auto-converted from std::io::Error with #[from] (codex-rs/ext/memories/src/backend.rs:161-162). It surfaces whenever an underlying filesystem operation in the local backend fails: reading a memory file (tokio::fs::read_to_string in local/read.rs:34), stat calls via metadata_or_none, or directory iteration while listing and searching. The embedded io::Error's kind and message carry the real cause, such as PermissionDenied, NotFound from a race, or InvalidData because a file in the store is not valid UTF-8.

Source

Thrown at codex-rs/ext/memories/src/backend.rs:161

    #[error("path '{path}' {reason}")]
    InvalidPath { path: String, reason: String },
    #[error("cursor '{cursor}' {reason}")]
    InvalidCursor { cursor: String, reason: String },
    #[error("path '{path}' was not found")]
    NotFound { path: String },
    #[error("line_offset must be a 1-indexed line number")]
    InvalidLineOffset,
    #[error("max_lines must be a positive integer")]
    InvalidMaxLines,
    #[error("line_offset exceeds file length")]
    LineOffsetExceedsFileLength,
    #[error("path '{path}' is not a file")]
    NotFile { path: String },
    #[error("queries must not be empty or contain empty strings")]
    EmptyQuery,
    #[error("all_within_lines.line_count must be a positive integer")]
    InvalidMatchWindow,
    #[error("I/O error while reading memories: {0}")]
    Io(#[from] std::io::Error),
}

impl MemoriesBackendError {
    pub fn invalid_filename(filename: impl Into<String>, reason: impl Into<String>) -> Self {
        Self::InvalidFilename {
            filename: filename.into(),
            reason: reason.into(),
        }
    }

    pub fn invalid_path(path: impl Into<String>, reason: impl Into<String>) -> Self {
        Self::InvalidPath {
            path: path.into(),
            reason: reason.into(),
        }
    }

View on GitHub (pinned to 339751715c)

Solutions

  1. Inspect the embedded std::io::Error (kind and message); it names the failing path and cause.
  2. For InvalidData (non-UTF-8), remove, rename, or re-save the offending file as UTF-8; the backend cannot read arbitrary bytes.
  3. For PermissionDenied, fix ownership and permissions on the memory root and its entries.
  4. For NotFound races or transient errors, re-list and retry once.
Defensive patterns

Strategy: try-catch

Validate before calling

// Rust - optional pre-flight for the common UTF-8/permission causes
async fn memory_readable(path: &std::path::Path) -> bool {
    match tokio::fs::read(path).await {
        Ok(bytes) => std::str::from_utf8(&bytes).is_ok(),
        Err(_) => false,
    }
}

Try / catch

match backend.read(request).await {
    Ok(resp) => { /* ... */ }
    Err(MemoriesBackendError::Io(e)) => match e.kind() {
        std::io::ErrorKind::PermissionDenied => { /* fix perms on the memory root */ }
        std::io::ErrorKind::InvalidData => { /* non-UTF-8 memory file: rename or remove it */ }
        std::io::ErrorKind::NotFound => { /* vanished mid-scan: re-list, retry once */ }
        _ => return Err(MemoriesBackendError::Io(e)),
    },
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: A memory file that is not valid UTF-8 (read_to_string fails with InvalidData); permission-denied entries under the memory root during read/list/search; a path that vanishes between the metadata check and the read; disk or lower-level I/O failures.

Common situations: Binary or non-UTF-8 files dropped into the memory directory; restrictive ownership after running under different accounts; cloud-sync tools churning the directory; full disks.

Related errors


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