openai/codex · error · MemoriesBackendError
path '{path}' is not a file
Error message
path '{path}' is not a file What it means
Returned by the memories read path (codex-rs/ext/memories/src/local/read.rs:30-32) when the path resolves and metadata exists but the entry is not a regular file, almost always a directory. read() only returns file content; symlinks are rejected earlier by a dedicated check. The list() API marks every entry with MemoryEntryType::File or MemoryEntryType::Directory exactly so callers can avoid this.
Source
Thrown at codex-rs/ext/memories/src/backend.rs:155
#[error("filename '{filename}' {reason}")]
InvalidFilename { filename: String, reason: String },
#[error("ad-hoc note must not be empty")]
EmptyAdHocNote,
#[error("ad-hoc note '{filename}' already exists")]
AdHocNoteAlreadyExists { filename: String },
#[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 {View on GitHub (pinned to 339751715c)
Solutions
- Call list() first and only read entries whose entry_type is MemoryEntryType::File.
- To inspect a directory, list() it with the directory as path.
- To locate content across files, use search(), which walks directories itself.
Example fix
// before
for entry in backend.list(list_req).await?.entries {
let resp = backend.read(read_req(entry.path)).await?; // NotFile on directories
}
// after
for entry in backend.list(list_req).await?.entries {
if is_memory_file(&entry) {
let resp = backend.read(read_req(entry.path)).await?;
}
} Defensive patterns
Strategy: type-guard
Validate before calling
// Rust - filter a listing down to readable files before calling read
let entries = backend.list(ListMemoriesRequest { path: Some(dir), cursor: None, max_results: 100 }).await?;
let readable: Vec<_> = entries.entries.into_iter().filter(is_memory_file).collect(); Type guard
// Rust - narrow MemoryEntry to entries read() accepts
fn is_memory_file(entry: &MemoryEntry) -> bool {
matches!(entry.entry_type, MemoryEntryType::File)
} Prevention
- Check MemoryEntryType before read(); directories are valid inputs only to list() and search().
- Never assume every list() result is a file.
- Prefer search() for content discovery instead of read()-ing every path.
When it happens
Trigger: Calling read() on a path that list() reported as MemoryEntryType::Directory; passing the memory root or a subfolder; reading a special file (fifo, device) that exists in the store.
Common situations: An agent or automation enumerating the store and reading every entry without checking entry_type; assuming list() results are all files; joining a folder with an empty filename.
Related errors
- approval_policy = "untrusted" is no longer supported; remove
- filename '{filename}' {reason}
- ad-hoc note must not be empty
- path '{path}' {reason}
- line_offset must be a 1-indexed line number
AI-assisted analysis of openai/codex@339751715c (2026-08-25).
Data as JSON: /api/errors/58bea4121d76d2b2.
Report an issue: GitHub.