{"record":{"id":"f586ff445ce569f7","repo":"pbakaus/impeccable","slug":"manual-edit-buffer-unreadable-err-message-st","errorCode":null,"errorMessage":"manual_edit_buffer_unreadable: ${err.message || String(err)}","messagePattern":"manual_edit_buffer_unreadable: (.+?)","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"plugin/skills/impeccable/scripts/live/manual-edits-buffer.mjs","lineNumber":44,"sourceCode":"}\n\nexport function readBufferStrict(cwd = process.cwd()) {\n  return readBufferInternal(cwd, { strict: true });\n}\n\nfunction readBufferInternal(cwd, { strict }) {\n  const filePath = getBufferPath(cwd);\n  try {\n    const raw = fs.readFileSync(filePath, 'utf-8');\n    const parsed = JSON.parse(raw);\n    if (!parsed || typeof parsed !== 'object' || !Array.isArray(parsed.entries)) {\n      if (strict) throw new Error('manual_edit_buffer_invalid_schema');\n      return { version: BUFFER_VERSION, entries: [] };\n    }\n    return { version: BUFFER_VERSION, entries: parsed.entries };\n  } catch (err) {\n    if (strict && err?.code !== 'ENOENT') {\n      throw new Error('manual_edit_buffer_unreadable: ' + (err.message || String(err)));\n    }\n    return { version: BUFFER_VERSION, entries: [] };\n  }\n}\n\nexport function writeBuffer(cwd, buffer) {\n  const filePath = getBufferPath(cwd);\n  fs.mkdirSync(path.dirname(filePath), { recursive: true });\n  fs.writeFileSync(filePath, JSON.stringify({ version: BUFFER_VERSION, entries: buffer.entries }, null, 2));\n}\n\n/**\n * Merge a new entry into the buffer. For each op in the new entry, if there's\n * already a buffered op for the same (pageUrl, ref), update that op's newText\n * and keep its original originalText (the true source state). Otherwise add\n * the op (creating an entry if needed).\n *\n * Multiple ops in one Save are allowed; each is keyed by (pageUrl, ref).","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/pbakaus/impeccable/blob/d14711ae3d1a1dd62dee61a358d27f107c51ccd0/plugin/skills/impeccable/scripts/live/manual-edits-buffer.mjs#L26-L62","documentation":"Thrown by readBufferStrict when the manual edits buffer file (.impeccable/live/pending-manual-edits.json) exists but cannot be read or parsed, and only in strict mode (ENOENT is tolerated even in strict). The library throws because staging a new manual edit requires a sound baseline to merge against, so it refuses to proceed over corrupt state rather than silently dropping buffered edits.","triggerScenarios":"Calling readBufferStrict(cwd) (or stageEntry, which calls it) when the buffer file is present but contains malformed JSON, or when a filesystem permission error blocks readFileSync. ENOENT is explicitly excluded so a missing file is fine.","commonSituations":"The buffer was hand-edited or partially written by a crashed process; an external tool overwrote the file with invalid JSON; a stale buffer left over from an aborted Save sits in .impeccable/live/.","solutions":["Inspect .impeccable/live/pending-manual-edits.json for syntax errors and fix or delete it (deleting loses only pending unstaged manual edits).","If the file is unneeded, remove it so the next read treats the missing file as empty (ENOENT is tolerated).","Ensure the directory is writable and not locked by another process, then retry the staging operation."],"exampleFix":"// before: file is corrupt and stageEntry throws\nawait stageEntry(cwd, newEntry);\n\n// after: validate/repair before staging\nimport { readBufferStrict } from './manual-edits-buffer.mjs';\ntry {\n  readBufferStrict(cwd);\n} catch {\n  fs.rmSync(getBufferPath(cwd), { force: true }); // drop corrupt buffer\n}\nawait stageEntry(cwd, newEntry);","handlingStrategy":"try-catch","validationCode":"import fs from 'node:fs';\nfunction isBufferReadable(filePath) {\n  if (!fs.existsSync(filePath)) return true; // ENOENT tolerated\n  try { JSON.parse(fs.readFileSync(filePath, 'utf-8')); return true; }\n  catch { return false; }\n}","typeGuard":"function isValidBuffer(parsed) {\n  return parsed !== null && typeof parsed === 'object' && Array.isArray(parsed.entries);\n}","tryCatchPattern":"try {\n  readBufferStrict(cwd);\n} catch (err) {\n  if (err.message.startsWith('manual_edit_buffer_unreadable')) {\n    fs.rmSync(getBufferPath(cwd), { force: true });\n  } else throw err;\n}","preventionTips":["Treat the buffer as a derived artifact: never hand-edit pending-manual-edits.json.","Write buffers atomically (temp file + rename) so a crash cannot leave a partial file.","Call readBuffer (non-strict) for tolerant reads and reserve readBufferStrict for staging, where a corrupt baseline must halt."],"tags":["filesystem","json","state","impeccable-live"],"backgroundTag":null,"analyzedSha":"d14711ae3d1a1dd62dee61a358d27f107c51ccd0","analyzedAt":"2026-08-13T00:52:25.771Z","schemaVersion":2},"datasetVersion":"2026-08-13T04:17:16.726Z"}