{"record":{"id":"19dd1f23d4662f3e","repo":"can1357/oh-my-pi","slug":"unseenlinesmessage-section-path-unseen-expected","errorCode":null,"errorMessage":"unseenLinesMessage(section.path, unseen, expected, { lines: revealed, truncated })","messagePattern":"unseenLinesMessage\\(section\\.path, unseen, expected, (.+?)\\)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/hashline/src/patcher.ts","lineNumber":653,"sourceCode":"\t\t\tif (line < 1 || line > sourceLines.length) continue;\n\t\t\tconst source = sourceLines[line - 1] ?? \"\";\n\t\t\tif (source.length > SEEN_LINE_REVEAL_MAX_COLUMNS) {\n\t\t\t\trevealed.push({ line, text: `${source.slice(0, SEEN_LINE_REVEAL_MAX_COLUMNS)}…` });\n\t\t\t\tcolumnTruncated = true;\n\t\t\t} else {\n\t\t\t\trevealed.push({ line, text: source });\n\t\t\t}\n\t\t}\n\t\tconst truncated = unseen.length > revealed.length || columnTruncated;\n\t\t// Only merge when the reveal covered every unseen anchor line in full\n\t\t// width. A prefix-truncated reveal would let the model split a blind\n\t\t// edit into <=cap-line retries and land it without ever running the\n\t\t// required range re-read; a column-clipped reveal would leave part of\n\t\t// each line unseen while the model receives an \"ok to retry\" signal.\n\t\tif (!truncated) {\n\t\t\tfor (const { line } of revealed) seen.add(line);\n\t\t}\n\t\tthrow new Error(unseenLinesMessage(section.path, unseen, expected, { lines: revealed, truncated }));\n\t}\n\t#mismatchError(\n\t\tsection: PatchSection,\n\t\tcanonicalPath: string,\n\t\tnormalized: string,\n\t\texpected: string,\n\t\thashRecognized: boolean,\n\t): MismatchError {\n\t\tconst actualFileHash = this.#recordFullSnapshot(canonicalPath, normalized);\n\t\treturn new MismatchError({\n\t\t\tpath: section.path,\n\t\t\texpectedFileHash: expected,\n\t\t\tactualFileHash,\n\t\t\tfileLines: normalized.split(\"\\n\"),\n\t\t\tanchorLines: section.collectAnchorLines(),\n\t\t\thashRecognized,\n\t\t});\n\t}","sourceCodeStart":635,"sourceCodeEnd":671,"githubUrl":"https://github.com/can1357/oh-my-pi/blob/969062200754ea02cfac922e5ebb8c608c079e15/packages/hashline/src/patcher.ts#L635-L671","documentation":"#assertSeenLines enforces that every line a hashline patch will edit was actually revealed to the caller in a prior read. If some expected lines were never seen, it throws unseenLinesMessage listing the section, unseen lines, and what was revealed, preventing blind edits against unobserved content. If the reveal was column-truncated, seen lines are not credited, forcing a full-range re-read.","triggerScenarios":"Applying a hashline patch to lines that were never included in a prior read of the section, or where prior reads were truncated (row cap or column clipping) so the patcher cannot confirm those lines were seen.","commonSituations":"An agent retrying an edit without re-reading the target region, read results capped by line/width limits, editing a different section of a file after only reading part of it, or stale session state after the file changed on disk.","solutions":["Re-read the target section (full lines, within the column cap) before retrying the edit","Retry the edit so the re-read marks the lines as seen, then re-issue the patch","Avoid clipped/truncated reads of the lines you intend to edit","If the file changed externally, restart the read-edit cycle from a fresh read"],"exampleFix":"// before\napplyPatch(edits); // lines 40-45 never read → throws\n// after\nconst section = readSection(path, 40, 45); // full, untruncated read\napplyPatch(edits); // lines now marked seen","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  applyPatch(edits);\n} catch (e) {\n  if (e.message.includes(\"were never read\") || /unseen/i.test(e.message)) {\n    await readSection(path, startLine, endLine); // full, untruncated read\n    applyPatch(edits); // retry after lines are marked seen\n  }\n}","preventionTips":["Always read the exact lines you intend to edit immediately before editing","Avoid truncated/clipped reads for regions that will be patched","Re-read after any external file change; never retry edits blind","Track which ranges were revealed and pre-check patch anchors against them"],"tags":["patching","state","read-before-write","editing"],"backgroundTag":"unseen-lines-edit-rejected","analyzedSha":"969062200754ea02cfac922e5ebb8c608c079e15","analyzedAt":"2026-08-31T10:29:35.737Z","schemaVersion":2},"datasetVersion":"2026-08-31T14:17:45.589Z"}