Hmbown/CodeWhale · error · Error

Codewhale runtime file contained only stream deltas or…

Error message

Codewhale runtime file contained only stream deltas or unreadable records.

What it means

After parsing a Codewhale runtime file, the snapshot is built from span-level events (item start/end, turn lifecycle, approvals, etc.). item.delta records are intentionally dropped as token stream fragments; if nothing else remains, the file produced no representable events, and the library refuses to return an empty trace.

Solutions

  1. Import the full runtime events journal (structured spans), not a token/delta stream log.
  2. Check that the source file is the runtime-events/v2 journal and not a partial or rotated fragment.
  3. If you only need token streams, use a stream viewer instead of this trace importer.
  4. Verify the file has non-delta events: filter lines whose event !== 'item.delta' and confirm the count is > 0 before importing.

Example fix

// before
const records = readJsonl('tokens.jsonl'); // all item.delta
const trace = fromCodewhaleRuntime(records);
// after
const records = readJsonl('session.jsonl');
if (!records.some(r => r?.event !== 'item.delta')) throw new Error('no span events in file');
const trace = fromCodewhaleRuntime(records);
Defensive patterns

Strategy: validation

Validate before calling

const hasSpans = (records) => records.some(r => r && typeof r === 'object' && r.event !== 'item.delta');
if (!hasSpans(records)) console.warn('file has only item.delta fragments; import will fail');

Type guard

const isSpanRecord = (r) => !!r && typeof r === 'object' && typeof r.event === 'string' && r.event !== 'item.delta';

Try / catch

try {
  return fromCodewhaleRuntime(records, filename);
} catch (e) {
  if (e.message.includes('only stream deltas')) return null; // no traceable spans in this file
  throw e;
}

Prevention

When it happens

Trigger: Calling snapshot() (directly or via fromCodewhaleRuntime) on a file whose records were all item.delta stream fragments, or where every line failed the isCodewhaleRuntimeRecord check and was discarded.

Common situations: Pointing the importer at a raw token-stream log rather than the structured event journal; a runtime configured to emit only deltas; a truncated or corrupted file where readable lines were all deltas; passing the wrong file from a directory of mixed logs.

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/20b387745c764000. Report an issue: GitHub.

Appendix: source

Thrown at pet/src/core/codewhale.ts:538

        continue;
      }
      this.push({
        schemaVersion: 1, id: `${eventName}:${rec.seq}`, traceId: threadId, parentId: turnId ? `turn:${turnId}` : undefined,
        startTime: relative, endTime: relative, agentId, name: eventName, category: classify(eventName),
        model, status: 'unknown', attributes: { 'codewhale.seq': rec.seq }, raw: rec,
      });
    }

    this.origin = origin; this.model = model; this.threadName = threadName; this.skippedDeltas = skippedDeltas;
  }
  snapshot(): Trace {
    const { events, open, requests, origin, model, skippedDeltas, filename } = this;
    const threadId = this.threadId ?? filename, threadName = this.threadName ?? threadId;
    const warnings: string[] = [];
    if (skippedDeltas) warnings.push(`Dropped ${skippedDeltas.toLocaleString()} item.delta records; they are token stream fragments, not spans. Item start/end remain the source of duration.`);
    for (const [id] of open) warnings.push(`Item ${id} started and never completed in this file; duration remains unknown.`);
    for (const request of requests.values()) warnings.push(`Request ${request.id} has no terminal receipt; its duration remains unknown in this file.`);
    if (!events.length) throw new Error('Codewhale runtime file contained only stream deltas or unreadable records.');
    const base = events.reduce((m, e) => Math.min(m, e.startTime), events[0]!.startTime);
    const normalized = events.map(event => ({ ...event, startTime: event.startTime - base, endTime: event.endTime - base,
      attributes: { ...event.attributes, ...(event.attributes['whalesong.error_onset_ms'] !== undefined
        ? { 'whalesong.error_onset_ms': errorOnsetOf(event) - base } : {}) } }));
    return {
      id: threadId,
      name: `Codewhale runtime · ${threadName}`,
      events: normalized,
      duration: Math.max(1, normalized.reduce((m, e) => Math.max(m, e.endTime, e.startTime, e.status === 'error' ? errorOnsetOf(e) : 0), 0)),
      originTime: origin !== undefined ? new Date(origin + base).toISOString() : '0 ms',
      source: 'codewhale',
      privacy: 'redact',
      warnings: [...new Set(warnings)],
      metadata: {
        sourceFormat: 'codewhale.runtime-events/v2',
        timeBasis: 'wall-clock',
        sourceFilename: filename,
        threadId,

View on GitHub (pinned to 433685b202)