{"record":{"id":"58f498fd8bfa2383","repo":"openai/codex","slug":"line-offset-exceeds-file-length","errorCode":null,"errorMessage":"line_offset exceeds file length","messagePattern":"line_offset exceeds file length","errorType":"validation","errorClass":"MemoriesBackendError","httpStatus":null,"severity":"warning","filePath":"codex-rs/ext/memories/src/backend.rs","lineNumber":153,"sourceCode":"#[derive(Debug, thiserror::Error)]\npub enum MemoriesBackendError {\n    #[error(\"filename '{filename}' {reason}\")]\n    InvalidFilename { filename: String, reason: String },\n    #[error(\"ad-hoc note must not be empty\")]\n    EmptyAdHocNote,\n    #[error(\"ad-hoc note '{filename}' already exists\")]\n    AdHocNoteAlreadyExists { filename: String },\n    #[error(\"path '{path}' {reason}\")]\n    InvalidPath { path: String, reason: String },\n    #[error(\"cursor '{cursor}' {reason}\")]\n    InvalidCursor { cursor: String, reason: String },\n    #[error(\"path '{path}' was not found\")]\n    NotFound { path: String },\n    #[error(\"line_offset must be a 1-indexed line number\")]\n    InvalidLineOffset,\n    #[error(\"max_lines must be a positive integer\")]\n    InvalidMaxLines,\n    #[error(\"line_offset exceeds file length\")]\n    LineOffsetExceedsFileLength,\n    #[error(\"path '{path}' is not a file\")]\n    NotFile { path: String },\n    #[error(\"queries must not be empty or contain empty strings\")]\n    EmptyQuery,\n    #[error(\"all_within_lines.line_count must be a positive integer\")]\n    InvalidMatchWindow,\n    #[error(\"I/O error while reading memories: {0}\")]\n    Io(#[from] std::io::Error),\n}\n\nimpl MemoriesBackendError {\n    pub fn invalid_filename(filename: impl Into<String>, reason: impl Into<String>) -> Self {\n        Self::InvalidFilename {\n            filename: filename.into(),\n            reason: reason.into(),\n        }\n    }","sourceCodeStart":135,"sourceCodeEnd":171,"githubUrl":"https://github.com/openai/codex/blob/339751715c64496cb86246bfb3935f40e309dd3d/codex-rs/ext/memories/src/backend.rs#L135-L171","documentation":"Returned by the memories read path when line_offset is a well-formed 1-indexed number but larger than the number of lines in the file. line_start_byte_offset (codex-rs/ext/memories/src/local/read.rs:53-72) scans for the start of the requested line by counting newlines and never reaches it, so the requested line does not exist. Unlike InvalidLineOffset, the request was valid; the file is simply shorter than the caller assumed.","triggerScenarios":"Paginating with an offset captured from an earlier read after the file shrank; computing line_offset from stale file info; another process (sync tool, second session) rewriting or trimming the memory file between reads; an offset greater than the total line count.","commonSituations":"Memory notes edited concurrently while a reader walks them; retry logic reusing offsets from an older, longer version; UIs that keep a scroll position as a line number.","solutions":["Treat this error as end-of-file and stop paginating.","Resynchronize by re-reading from line_offset 1 (or re-listing) when it fires.","If you must continue, count the file's lines first and clamp line_offset to that count.","Drive pagination from the latest response's start_line_number and truncated flag, not cached offsets."],"exampleFix":"// before\nloop {\n    let resp = backend.read(req_at(offset)).await?; // fails at EOF\n    if !resp.truncated { break; }\n    offset += 200;\n}\n\n// after\nloop {\n    let resp = match backend.read(req_at(offset)).await {\n        Ok(resp) => resp,\n        Err(MemoriesBackendError::LineOffsetExceedsFileLength) => break, // end of file\n    };\n    if !resp.truncated { break; }\n    offset += 200;\n}","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"match backend.read(request).await {\n    Ok(resp) => { /* render */ }\n    Err(MemoriesBackendError::LineOffsetExceedsFileLength) => {\n        // normal end-of-pagination outcome: stop, do not surface as failure\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Expect memory files to change between reads; EOF is a normal outcome, not an exceptional one.","Derive the next offset from the newest response, never from a cached one.","After this error, resynchronize with a fresh read from line 1 before further paging."],"tags":["rust","codex","memories","pagination","eof","stale-state"],"backgroundTag":"read-past-eof","analyzedSha":"339751715c64496cb86246bfb3935f40e309dd3d","analyzedAt":"2026-08-25T05:35:09.876Z","schemaVersion":2},"datasetVersion":"2026-08-25T06:17:31.827Z"}