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
- Inspect snapshot.diagnostics to find the offending line numbers in the journal file.
- Delete or repair the corrupt lines in the journal; the next rebuild skips invalid entries.
- 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
- Write journal entries atomically (one JSON object per line, append-only).
- Validate entries with isJournalEntry before appending.
- Periodically compact the journal so corruption surface area stays small.
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
- manual_edit_buffer_unreadable: ${err.message || String(err)}
- config.json must be an object
- config.files (non-empty string array) required
- config.files must contain only non-empty strings
- config.exclude, if present, must be a string array
AI-assisted analysis of pbakaus/impeccable@d14711ae3d (2026-08-13).
Data as JSON: /api/errors/fda9cc99d4b29fd4.
Report an issue: GitHub.