Hmbown/CodeWhale · error · Error
Record : invalid status.
Error message
Record ${index + 1}: invalid status. What it means
normalizedEvent restricts the status field to the closed set ['pending','running','success','error','unknown']. Any other value (wrong casing, synonyms like 'failed' or 'ok', numbers, nulls) is rejected with this error.
Solutions
- Map the external status into one of pending/running/success/error/unknown before ingest.
- Fix casing to exact lowercase literals.
- Use 'unknown' when no faithful mapping exists, instead of inventing a value.
Example fix
// before
{ "id": "a1", "traceId": "t1", "name": "step", "status": "Failed" }
// after
{ "id": "a1", "traceId": "t1", "name": "step", "status": "error" } Defensive patterns
Strategy: validation
Validate before calling
const STATUSES = ['pending', 'running', 'success', 'error', 'unknown'];
if (record.status !== undefined && !STATUSES.includes(record.status))
throw new Error(`status must be one of ${STATUSES.join(', ')}`); Type guard
type Status = 'pending' | 'running' | 'success' | 'error' | 'unknown'; const isStatus = (s: unknown): s is Status => typeof s === 'string' && (['pending','running','success','error','unknown'] as const).includes(s as Status);
Try / catch
try {
traces = importTrace(text, file);
} catch (e) {
if (e instanceof Error && e.message === 'invalid status' || (e instanceof Error && e.message.includes('invalid status')) && e.message.includes('Record')) {
console.error('Normalize statuses to the five allowed literals before import');
} else throw e;
} Prevention
- Centralize status mapping (e.g. 'Failed' -> 'error') in one producer-side function.
- Always lowercase statuses before emitting.
- Use 'unknown' as the fallback for unmappable external statuses.
When it happens
Trigger: Ingesting a record with a.status set to something outside the five allowed literals, e.g. status:'Failed', status:'complete', status:0, or status:null.
Common situations: Mapping statuses from another system (HTTP 500 -> 'failed', CI 'passed') without translating to this vocabulary; case sensitivity mistakes ('Success'); tests that reuse fixtures from a different tool.
Understand the failure class
Background: Invalid enum value errors: "Unknown type", "Invalid scope", "must be one of" — when a string is not on the library's allowed list — this error's family across 23 libraries.
Related errors
- Unknown category " ". Use "other" plus subtype for…
- agent profile reasoning_effort must be one of: inherit…
- Choose approve or decline
- clipboard action must be "read" or "write
- computer action must be list, switch, register, spawn or…
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/607d478a00e134e9.
Report an issue: GitHub.
Appendix: source
Thrown at pet/src/core/ingest.ts:133
if (typeof v === 'number' && !Number.isSafeInteger(v)) throw new Error(`${field} lost precision: encode OTLP nanoseconds as a decimal string.`);
const s = String(v ?? '');
if (!/^\d{1,20}$/.test(s) || BigInt(s) > 18446744073709551615n) throw new Error(`Invalid ${field}: expected an OTLP nanosecond integer string.`);
return BigInt(s);
}
function otelStatus(v: unknown): Status {
const c = obj(v).code;
return c === 2 || c === 'STATUS_CODE_ERROR' ? 'error' : c === 1 || c === 'STATUS_CODE_OK' ? 'success' : 'unknown';
}
function normalizedEvent(v: unknown, index: number): WhaleEvent {
const a = obj(v), id = str(a.id), traceId = str(a.traceId), name = str(a.name);
if (!id || !traceId || !name) throw new Error(`Record ${index + 1} requires nonempty id, traceId, and name.`);
if (a.schemaVersion !== undefined && a.schemaVersion !== 1) throw new Error(`Record ${index + 1}: unsupported schemaVersion ${a.schemaVersion}.`);
const startTime = number(a.startTime, 'startTime', false)!;
const endTime = number(a.endTime, 'endTime') ?? startTime;
if (endTime < startTime) throw new Error(`Record ${index + 1}: endTime precedes startTime.`);
if (a.category !== undefined && !CATEGORIES.includes(a.category)) throw new Error(`Unknown category "${a.category}". Use "other" plus subtype for extensions.`);
const allowed: Status[] = ['pending', 'running', 'success', 'error', 'unknown'];
if (a.status !== undefined && !allowed.includes(a.status)) throw new Error(`Record ${index + 1}: invalid status.`);
const at = obj(a.attributes);
return {
schemaVersion: 1, id, traceId, name, parentId: str(a.parentId), startTime, endTime,
openEnded: a.endTime === undefined || a.openEnded === true,
agentId: str(a.agentId) ?? 'unattributed', agentType: str(a.agentType), parentAgentId: str(a.parentAgentId),
category: a.category ?? categoryFor(name, at), subtype: str(a.subtype),
model: str(a.model), provider: str(a.provider), tool: str(a.tool),
inputTokens: nonnegative(a.inputTokens, 'inputTokens'), outputTokens: nonnegative(a.outputTokens, 'outputTokens'),
cachedTokens: nonnegative(a.cachedTokens, 'cachedTokens'), cost: nonnegative(a.cost, 'cost'),
costCurrency: str(a.costCurrency), latency: nonnegative(a.latency, 'latency'),
contextTokens: nonnegative(a.contextTokens, 'contextTokens'), contextLimit: nonnegative(a.contextLimit, 'contextLimit'),
retry: nonnegative(a.retry, 'retry'), status: a.status ?? 'unknown',
sourceId: str(a.sourceId), targetId: str(a.targetId), targetType: str(a.targetType),
links: list(a.links).filter(x => typeof x?.traceId === 'string' && typeof x?.spanId === 'string'),
attributes: at, payload: a.payload, raw: a.raw ?? v,
observation: a.observation === undefined ? undefined : validateObservation(a.observation),
};
}View on GitHub (pinned to 433685b202)