Hmbown/CodeWhale · error · Error

Runtime import cancelled: a line is not a Codewhale runtime…

Error message

Runtime import cancelled: a line is not a Codewhale runtime event record. No rows were skipped.

What it means

Every line of a runtime export must be a valid Codewhale runtime event record, checked by isCodewhaleRuntimeRecord. If any record fails the shape check, the whole import is cancelled with no rows skipped — the importer is all-or-nothing to avoid a silently partial timeline. The message deliberately states the abort semantics.

Solutions

  1. Inspect the runtime file and remove or fix lines that are not valid runtime records (check seq, event, timestamp, thread_id).
  2. Re-export a single thread cleanly from Codewhale.
  3. Validate each line with the same shape predicate before importing (see validation code).
  4. Ensure the file is the newline-delimited record format, not wrapped JSON.

Example fix

// before (mixed content)
{"note":"export started"}
{"seq":1,"event":"item.completed","thread_id":"t1","timestamp":"..."}
// after
{"seq":1,"event":"item.completed","thread_id":"t1","timestamp":"..."}
Defensive patterns

Strategy: validation

Validate before calling

const isRecord = (r) => r && typeof r === 'object' && !Array.isArray(r) && Number.isFinite(r.seq) && typeof r.event === 'string' && typeof r.thread_id === 'string';
if (!records.every(isRecord)) throw new Error('File contains non-record lines');

Type guard

const isCodewhaleRuntimeRecord = (v) => typeof v === 'object' && v !== null && 'seq' in v && 'event' in v && 'thread_id' in v;

Try / catch

try { importRuntime(lines); } catch (e) { if (e.message.includes('not a Codewhale runtime event record')) rejectWholeFile(lines); else throw e; }

Prevention

When it happens

Trigger: Importing a runtime file containing a non-record line: a JSON header/footer object, a log line, a null, an array element, or a record missing required fields like seq/event/timestamp/thread_id.

Common situations: Concatenating exports from different versions; a partial/truncated last line; exporting stdout that mixes progress output with records; passing a JSON array instead of newline-delimited records.

Understand the failure class

Background: Schema validation failed / invalid input schema: payload rejected because its shape doesn't match the expected schema — this error's family across 28 libraries.

Related errors


AI-assisted analysis of Hmbown/CodeWhale@73e0f67d83 (2026-09-22). Data as JSON: /api/errors/e1e7b55d1093270b. Report an issue: GitHub.

Appendix: source

Thrown at crates/tui/src/tui/pet_watch/pet-native.js:2310

    append(records) {
        if (!records.length)
            return;
        const { events, open, requests } = this;
        const threadId = this.threadId ?? str(obj(records[0]).thread_id) ?? this.filename;
        this.threadId = threadId;
        let { origin, model, skippedDeltas } = this;
        let threadName = this.threadName ?? threadId;
        const stamp = (rec) => {
            const t = parseTime(rec.timestamp);
            if (t === undefined)
                throw new Error(`Runtime event seq ${rec.seq} is missing a usable timestamp.`);
            if (origin === undefined)
                origin = t;
            return t - origin;
        };
        for (const raw of records) {
            if (!isCodewhaleRuntimeRecord(raw))
                throw new Error('Runtime import cancelled: a line is not a Codewhale runtime event record. No rows were skipped.');
            this.recordCount++;
            const rec = obj(raw);
            if (rec.thread_id !== threadId)
                throw new Error('Runtime import contains multiple threads. Export one thread before importing.');
            const eventName = rec.event;
            if (eventName === 'item.delta') {
                skippedDeltas++;
                continue;
            }
            const payload = obj(rec.payload);
            const item = obj(payload.item);
            const turn = obj(payload.turn);
            const thread = obj(payload.thread);
            const relative = stamp(rec);
            const turnId = str(rec.turn_id) ?? str(payload.turn_id);
            const itemId = str(rec.item_id) ?? str(item.id);
            const agentId = 'parent';
            if (str(thread.model))

View on GitHub (pinned to 73e0f67d83)