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
- Inspect the runtime file and remove or fix lines that are not valid runtime records (check seq, event, timestamp, thread_id).
- Re-export a single thread cleanly from Codewhale.
- Validate each line with the same shape predicate before importing (see validation code).
- 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
- Validate every line before import; the import is all-or-nothing.
- Never mix export output with logs or headers.
- Confirm the file is newline-delimited records, not wrapped JSON.
- Re-export cleanly instead of concatenating old exports.
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
- Runtime import cancelled: a line is not a Codewhale runtime…
- bundle contains conflicting or rejected entries
- Choose one recording to import.
- Codewhale runtime event file is empty.
- CRON field contains an empty list item
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)