Hmbown/CodeWhale · error · Error
Codewhale session contains no journal entries or messages.
Error message
Codewhale session contains no journal entries or messages.
What it means
fromCodewhaleSession() converts a Codewhale session document (journal plus optional top-level messages) into a trace. It throws when the active journal yields no entries and the document also has no messages array, because a session with no inspectable content cannot produce any events. This is a fail-fast guard before the expensive entry-to-event conversion.
Solutions
- Inspect the session JSON: confirm root.journal has entries (not all filtered as inactive) or root.messages is a non-empty array.
- Re-export the session after at least one completed turn so journal entries exist.
- If a session may legitimately be empty, guard the call site and skip instead of importing.
Example fix
// before
const trace = fromCodewhaleSession(doc, file);
// after
if (!doc?.journal?.entries?.length && !doc?.messages?.length) { console.warn(`skipping ${file}: empty session`); return; }
const trace = fromCodewhaleSession(doc, file); Defensive patterns
Strategy: validation
Validate before calling
const entries = doc?.journal?.entries ?? [];
const messages = Array.isArray(doc?.messages) ? doc.messages : [];
if (entries.length === 0 && messages.length === 0) { skip(file); return; }
const trace = fromCodewhaleSession(doc, file); Type guard
const hasSessionContent = (d: any): boolean => !!d && ((d.journal?.entries?.length ?? 0) > 0 || (Array.isArray(d.messages) && d.messages.length > 0));
Try / catch
try { trace = fromCodewhaleSession(doc, file); }
catch (e) { if (e.message.includes('no journal entries or messages')) return null; throw e; } Prevention
- Skip zero-byte or metadata-only session files before import.
- Only export sessions after at least one completed turn.
- Batch imports with per-file try/catch so one empty session doesn't abort the run.
When it happens
Trigger: Importing a session JSON where root.journal has no active entries (all filtered out by activeJournalEntries) and root.messages is absent or an empty array — e.g. a brand-new session, a session whose entries were all pruned, or reading the wrong file.
Common situations: Exporting a session immediately after creation before any turn ran, exporting after a session reset/cleanup, or pointing the importer at a metadata-only stub file.
Understand the failure class
Background: EmptyResultError / "no results found": when an API or scraper succeeds but returns zero rows — this error's family across 9 libraries.
Related errors
- Codewhale session produced no inspectable events.
- Codewhale runtime event file is empty.
- Codewhale runtime event file is empty.
- Codewhale runtime file contained only stream deltas or…
- Codewhale session contains no journal entries or messages.
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/3ea2cd66dd5a6825.
Report an issue: GitHub.
Appendix: source
Thrown at pet/src/core/codewhale.ts:157
const times = entries.map(e => parseTime(e.created_at)).filter((n): n is number => n !== undefined);
if (times.length < 2) return false;
const span = Math.max(...times) - Math.min(...times);
const envelope = created !== undefined && updated !== undefined ? updated - created : 0;
return envelope >= ENVELOPE_MIN_MS && span < COLLAPSED_SPAN_MS;
}
function pushEvent(events: WhaleEvent[], event: WhaleEvent): void {
events.push(event);
}
export function fromCodewhaleSession(document: unknown, filename = 'Codewhale session', maxEvents = 250_000): Trace {
const root = obj(document);
const metadata = obj(root.metadata);
const sessionId = str(metadata.id) ?? filename;
const journal = obj(root.journal);
const { entries, warnings } = activeJournalEntries(journal);
const sourceEntries: Obj[] = entries.length ? entries : (Array.isArray(root.messages) ? root.messages.map((message: unknown, i: number) => ({ id: `${sessionId}/message/${i}`, kind: 'message', message })) : []);
if (!sourceEntries.length) throw new Error('Codewhale session contains no journal entries or messages.');
const created = parseTime(metadata.created_at);
const updated = parseTime(metadata.updated_at);
const orderOnly = collapsedTimestamps(sourceEntries, created, updated);
if (orderOnly) {
warnings.push('Journal created_at values are collapsed to last-save time, not execution time. The time axis is journal order (1 ms per emitted event), not wall-clock duration. Gap, burst, and cycle-period findings are not execution-time claims.');
} else {
const times = sourceEntries.map(e => parseTime(e.created_at)).filter((n): n is number => n !== undefined);
if (!times.length) warnings.push('Journal entries have no usable timestamps. The time axis is journal order.');
}
const events: WhaleEvent[] = [];
const pending = new Map<string, number>();
let seq = 0;
const originWall = orderOnly ? undefined : sourceEntries.map(e => parseTime(e.created_at)).find((n): n is number => n !== undefined);
const agentId = 'parent';
const model = str(metadata.model);
const provider = str(metadata.model_provider);
View on GitHub (pinned to 433685b202)