Hmbown/CodeWhale · error · Error

Codewhale session produced no inspectable events.

Error message

Codewhale session produced no inspectable events.

What it means

Thrown after parsing a Codewhale session snapshot when the events array ends up empty. The importer requires at least one inspectable event to build a timeline; an import that would produce zero events is treated as invalid input rather than an empty result. It prevents the subsequent timeline base computation (events[0]) from failing on an empty array.

Solutions

  1. Verify the snapshot file actually contains message/item entries with content or text.
  2. Re-export the Codewhale session and confirm the export is non-empty and complete.
  3. Check the parser still matches your Codewhale version's snapshot schema; update the exporter/importer pair together.
  4. Inspect a few entries with the same parsing helpers (str/obj) to see why they are rejected.

Example fix

// before
const events = importCodewhaleSession(readFile(path));
// after
const raw = JSON.parse(readFile(path));
if (!raw.entries?.some(e => e.message?.content?.length || e.text)) {
  throw new Error('Snapshot has no inspectable entries; re-export the session.');
}
const events = importCodewhaleSession(raw);
Defensive patterns

Strategy: validation

Validate before calling

const entries = snapshot.entries ?? [];
const inspectable = entries.some(e => (e.message?.content?.length ?? 0) > 0 || e.text || e.message?.text);
if (!inspectable) throw new Error('Snapshot has no inspectable entries; re-export before importing.');

Type guard

function hasInspectableEntries(snapshot) {
  return Array.isArray(snapshot?.entries) && snapshot.entries.some(
    e => e && (typeof e.text === 'string' || typeof e.message?.text === 'string' || Array.isArray(e.message?.content))
  );
}

Try / catch

try {
  importCodewhaleSession(snapshot);
} catch (e) {
  if (String(e.message).includes('no inspectable events')) {
    console.error('Export appears empty or format-incompatible; re-export the session.');
  } else throw e;
}

Prevention

When it happens

Trigger: Running the session importer on a snapshot whose entries are all skipped: entries with no usable message content, no recognized role, no text, or no parseable timestamps, so no event is ever pushed before the !events.length check at pet/ios/Resources/pet-native.js:2151.

Common situations: Exporting a session that only contains tool-call metadata without message content; a truncated or corrupt export file; a version change in Codewhale's snapshot format so the parser no longer recognizes entries; passing the wrong file (e.g. a config or log file) to the importer.

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


AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15). Data as JSON: /api/errors/1c42dadbf8eaf99f. Report an issue: GitHub.

Appendix: source

Thrown at pet/ios/Resources/pet-native.js:2151

            else {
                const text = str(block.text) ?? '';
                const operate = text.includes('codewhale:runtime_event');
                const user = role === 'user' || role === 'User';
                pushEvent(events, {
                    schemaVersion: 1, id: idBase, traceId: sessionId, parentId: parentEventId,
                    startTime: t.start, endTime: t.start, agentId,
                    name: operate ? 'operate_contract' : user ? 'user_message' : 'assistant_message',
                    category: operate ? 'orchestration' : user ? 'human' : 'communication',
                    model, provider, status: 'success',
                    attributes: { 'codewhale.entry_id': entryId, 'codewhale.seq': seq, role: role ?? 'unknown' },
                    payload: { text: clip(text) }, raw,
                });
            }
            seq += 1;
        }
    }
    if (!events.length)
        throw new Error('Codewhale session produced no inspectable events.');
    for (const event of events) {
        if (event.openEnded && event.tool)
            warnings.push(`Tool ${event.id} has no matching tool_result in this snapshot; duration remains unknown.`);
    }
    const base = events.reduce((m, e) => Math.min(m, e.startTime), events[0].startTime);
    for (const event of events) {
        event.startTime -= base;
        event.endTime -= base;
    }
    const cost = obj(metadata.cost);
    const sessionCost = num(cost.session_cost_usd);
    const duration = Math.max(1, events.reduce((m, e) => Math.max(m, e.endTime, e.startTime), 0));
    const uniqueWarnings = [...new Set(warnings)];
    return {
        id: sessionId,
        name: titleOfSession(metadata, filename),
        events,
        duration,

View on GitHub (pinned to 433685b202)