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

Thrown at the end of a runtime import when, after all parsing, no events could be built — the file only contained item.delta stream fragments (which are skipped by design) or unreadable records. Since a timeline needs at least one real start/end pair, an all-deltas file yields nothing importable and is rejected instead of returning an empty timeline. Warnings about dropped deltas are still collected first.

Solutions

  1. Re-export the thread and confirm the export contains item start/end records, not just deltas.
  2. Check the export is complete (not truncated before any item started).
  3. Verify importer and exporter versions match so item records are recognized.
  4. Import a different/earlier snapshot of the thread that includes real item events.

Example fix

// before
const events = runtime.import(file, threadId); // may throw on deltas-only file
// after
const records = readRecords(file);
if (!records.some(r => r.event === 'item.started' || r.event === 'item.completed')) {
  throw new Error('File has no item start/end records; re-export the thread.');
}
const events = runtime.import(file, threadId);
Defensive patterns

Strategy: validation

Validate before calling

const hasItems = records.some(r => !r.event?.startsWith('item.delta'));
if (!hasItems) throw new Error('File contains only item.delta records; nothing to import. Re-export the thread.');

Type guard

function hasImportableEvents(records) {
  return Array.isArray(records) && records.some(r => typeof r?.event === 'string' && !r.event.startsWith('item.delta'));
}

Try / catch

try {
  const result = runtime.import(file, threadId);
} catch (e) {
  if (String(e.message).includes('only stream deltas')) {
    console.error('No importable item events in this file; use a full thread export.');
  } else throw e;
}

Prevention

When it happens

Trigger: Importing a runtime file whose non-skipped records all failed to become events: e.g. only item.delta records, only turn.lifecycle records, or item start/end records that could not be resolved, so events.length === 0 at the check in pet/ios/Resources/pet-native.js:2482.

Common situations: Exporting a thread that never produced any completed items (interrupted immediately); a file of only token-stream deltas; a schema mismatch where start/end records are not recognized; pointing the importer at a delta-only capture stream instead of the full export.

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

Appendix: source

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

            });
        }
        this.origin = origin;
        this.model = model;
        this.threadName = threadName;
        this.skippedDeltas = skippedDeltas;
    }
    snapshot() {
        const { events, open, requests, origin, model, skippedDeltas, filename } = this;
        const threadId = this.threadId ?? filename, threadName = this.threadName ?? threadId;
        const warnings = [];
        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': (0, model_js_1.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' ? (0, model_js_1.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)