pbakaus/impeccable · warning · Error

entry is not object

Error message

entry is not object

What it means

Thrown while replaying the session journal in rebuildSnapshotFromJournal when a non-blank journal line parses as JSON but yields a value that is not an object (e.g. a bare number or string). The message is collected as a diagnostic, not rethrown, so journal corruption is reported without aborting the rebuild.

Source

Thrown at plugin/skills/impeccable/scripts/live/session-store.mjs:297

  if (snapshot.mountedVariants.length > 0) return 'mounted';
  if (snapshot.mountFailures.length > 0) return 'failed';
  if (snapshot.generationCompletedAt) return 'pending';
  return null;
}

function rebuildSnapshotFromJournal(journalPath, id) {
  let snapshot = baseSnapshot(id);
  const diagnostics = [];
  let nextSeq = 1;
  if (!fs.existsSync(journalPath)) return { snapshot, diagnostics, nextSeq };

  const lines = fs.readFileSync(journalPath, 'utf-8').split('\n');
  for (let i = 0; i < lines.length; i++) {
    const line = lines[i];
    if (!line.trim()) continue;
    try {
      const entry = JSON.parse(line);
      if (!entry || typeof entry !== 'object') throw new Error('entry is not object');
      if (Number.isInteger(entry.seq)) nextSeq = Math.max(nextSeq, entry.seq + 1);
      snapshot = applyEvent(snapshot, entry);
    } catch (err) {
      diagnostics.push({
        error: 'journal_parse_failed',
        line: i + 1,
        message: err.message,
      });
    }
  }
  snapshot.diagnostics = [...snapshot.diagnostics, ...diagnostics];
  return { snapshot, diagnostics, nextSeq };
}

function applyEvent(snapshot, entry) {
  const event = entry.event || entry;
  const next = {
    ...snapshot,

View on GitHub (pinned to d14711ae3d)

Solutions

  1. Inspect snapshot.diagnostics to find the offending line numbers in the journal file.
  2. Delete or repair the corrupt lines in the journal; the next rebuild skips invalid entries.
  3. If the journal is unrecoverable, archive it and let the session reinitialize from baseSnapshot.

Example fix

// before: corrupt journal line `42` throws inside the try
// the rebuild swallows it into diagnostics; snapshot is still returned

// after: filter non-object lines when writing the journal
function appendJournalEntry(filePath, entry) {
  if (!entry || typeof entry !== 'object') return; // guard
  fs.appendFileSync(filePath, JSON.stringify(entry) + '\n');
}
Defensive patterns

Strategy: try-catch

Validate before calling

function isJournalLineValid(line) {
  if (!line.trim()) return true;
  try {
    const v = JSON.parse(line);
    return v !== null && typeof v === 'object';
  } catch { return false; }
}

Type guard

function isJournalEntry(value) {
  return value !== null && typeof value === 'object' && (!('seq' in value) || Number.isInteger(value.seq));
}

Try / catch

// rebuildSnapshotFromJournal already catches per-line and records diagnostics;
// surface diagnostics to detect corruption:
const { snapshot, diagnostics } = rebuildSnapshotFromJournal(journalPath, id);
if (diagnostics.length) console.warn('journal corruption:', diagnostics);

Prevention

When it happens

Trigger: A session journal line under .impeccable/live that is valid JSON but not an object, such as `42` or `"text"`. Each offending line produces a journal_parse_failed diagnostic carrying this message.

Common situations: Concurrent writers appending partial/corrupt entries, a hand-edit that left a stray value, or a version-skewed writer emitting an unexpected shape.

Related errors


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