pbakaus/impeccable · error · Error

manual_edit_buffer_unreadable: ${err.message || String(err)}

Error message

manual_edit_buffer_unreadable: ${err.message || String(err)}

What it means

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.

Source

Thrown at plugin/skills/impeccable/scripts/live/manual-edits-buffer.mjs:44

}

export function readBufferStrict(cwd = process.cwd()) {
  return readBufferInternal(cwd, { strict: true });
}

function readBufferInternal(cwd, { strict }) {
  const filePath = getBufferPath(cwd);
  try {
    const raw = fs.readFileSync(filePath, 'utf-8');
    const parsed = JSON.parse(raw);
    if (!parsed || typeof parsed !== 'object' || !Array.isArray(parsed.entries)) {
      if (strict) throw new Error('manual_edit_buffer_invalid_schema');
      return { version: BUFFER_VERSION, entries: [] };
    }
    return { version: BUFFER_VERSION, entries: parsed.entries };
  } catch (err) {
    if (strict && err?.code !== 'ENOENT') {
      throw new Error('manual_edit_buffer_unreadable: ' + (err.message || String(err)));
    }
    return { version: BUFFER_VERSION, entries: [] };
  }
}

export function writeBuffer(cwd, buffer) {
  const filePath = getBufferPath(cwd);
  fs.mkdirSync(path.dirname(filePath), { recursive: true });
  fs.writeFileSync(filePath, JSON.stringify({ version: BUFFER_VERSION, entries: buffer.entries }, null, 2));
}

/**
 * Merge a new entry into the buffer. For each op in the new entry, if there's
 * already a buffered op for the same (pageUrl, ref), update that op's newText
 * and keep its original originalText (the true source state). Otherwise add
 * the op (creating an entry if needed).
 *
 * Multiple ops in one Save are allowed; each is keyed by (pageUrl, ref).

View on GitHub (pinned to d14711ae3d)

Solutions

  1. Inspect .impeccable/live/pending-manual-edits.json for syntax errors and fix or delete it (deleting loses only pending unstaged manual edits).
  2. If the file is unneeded, remove it so the next read treats the missing file as empty (ENOENT is tolerated).
  3. Ensure the directory is writable and not locked by another process, then retry the staging operation.

Example fix

// before: file is corrupt and stageEntry throws
await stageEntry(cwd, newEntry);

// after: validate/repair before staging
import { readBufferStrict } from './manual-edits-buffer.mjs';
try {
  readBufferStrict(cwd);
} catch {
  fs.rmSync(getBufferPath(cwd), { force: true }); // drop corrupt buffer
}
await stageEntry(cwd, newEntry);
Defensive patterns

Strategy: try-catch

Validate before calling

import fs from 'node:fs';
function isBufferReadable(filePath) {
  if (!fs.existsSync(filePath)) return true; // ENOENT tolerated
  try { JSON.parse(fs.readFileSync(filePath, 'utf-8')); return true; }
  catch { return false; }
}

Type guard

function isValidBuffer(parsed) {
  return parsed !== null && typeof parsed === 'object' && Array.isArray(parsed.entries);
}

Try / catch

try {
  readBufferStrict(cwd);
} catch (err) {
  if (err.message.startsWith('manual_edit_buffer_unreadable')) {
    fs.rmSync(getBufferPath(cwd), { force: true });
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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/.

Related errors


AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13). Data as JSON: /api/errors/f586ff445ce569f7. Report an issue: GitHub.