Hmbown/CodeWhale · error · Error

The file contains no events.

Error message

The file contains no events.

What it means

After normalization, if the parsed input yields zero events, importTrace throws rather than returning an empty trace list, since an import file with no events is never a meaningful result. This fires only for the non-OTLP path after normalizedEvent mapping (or when records is empty).

Solutions

  1. Verify the file actually contains event records and uses the expected whalesong/OTLP format.
  2. Re-export with a time range/filter that includes at least one event.
  3. Check normalizedEvent compatibility: field names like traceId, id, startTime must be present in the source records.

Example fix

// before
importTrace(JSON.stringify([]));
// after
const doc = JSON.parse(text);
if (!doc || (Array.isArray(doc) && doc.length === 0)) throw new Error('Export contains no events; widen the export filter.');
importTrace(text);
Defensive patterns

Strategy: validation

Validate before calling

const doc = JSON.parse(text);
const hasEvents = Array.isArray(doc) ? doc.length > 0 : Array.isArray(doc.resourceSpans) || doc.events?.length > 0 || true;
if (!hasEvents) throw new Error('Import contains no events.');

Type guard

function hasEvents(doc: unknown): boolean {
  if (Array.isArray(doc)) return doc.length > 0;
  if (doc && typeof doc === 'object') {
    const d = doc as Record<string, unknown>;
    return Array.isArray(d.resourceSpans) || Array.isArray(d.events);
  }
  return false;
}

Try / catch

try {
  importTrace(text);
} catch (e) {
  if (e instanceof Error && e.message === 'The file contains no events.') {
    console.error('The export matched nothing; widen the filter or fix the format.');
  }
}

Prevention

When it happens

Trigger: Passing a valid JSON document that is not recognized as events (e.g. an empty array [], an object without recognizable event fields), or options/records resolving to an empty list; OTLP input with zero spans produces the same outcome via fromOTLP returning [].

Common situations: Exporting with a filter that matched nothing; wrong format (metadata-only file); schema drift where normalizedEvent silently expects different field names; hand-building a bundle with an empty events array.

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

Appendix: source

Thrown at pet/src/core/ingest.ts:259

    trace.events = trace.events.map(e => privacyEvent(e, mode));
    return [trace];
  }
  const records = Array.isArray(safe) ? safe : Array.isArray(root.events) ? root.events : null;
  if (isCodewhaleRuntimeDocument(records ?? [safe])) {
    const trace = fromCodewhaleRuntime(records ?? [safe], filename, maxEvents);
    trace.privacy = mode;
    trace.events = trace.events.map(e => privacyEvent(e, mode));
    return [trace];
  }
  const isOTLP = Array.isArray(root.resourceSpans);
  let all: WhaleEvent[], origins = new Map<string, string>(), warnings: string[] = [];
  if (isOTLP) { const r = fromOTLP(root, maxEvents); all = r.events; origins = r.origins; warnings = r.warnings; }
  else {
    const incoming = records ?? [safe];
    if (incoming.length > maxEvents) throw new Error(`Import exceeds the ${maxEvents.toLocaleString()} event limit.`);
    all = incoming.map(normalizedEvent);
  }
  if (!all.length) throw new Error('The file contains no events.');
  const groups = new Map<string, WhaleEvent[]>(), ids = new Set<string>();
  for (const e of all) {
    const key = `${e.traceId}\0${e.id}`;
    if (ids.has(key)) throw new Error(`Duplicate event identity (${e.traceId}, ${e.id}). Import cancelled.`);
    ids.add(key);
    const group = groups.get(e.traceId) ?? []; group.push(privacyEvent(e, mode)); groups.set(e.traceId, group);
    if (groups.size > maxTraces) throw new Error(`This import contains more than ${maxTraces} traces. Split it by trace ID.`);
  }
  return [...groups].map(([id, events]) => {
    events.sort((a, b) => a.startTime - b.startTime || a.id.localeCompare(b.id));
    const base = isOTLP ? 0 : events[0].startTime;
    if (!isOTLP && events.some(e => Math.abs(e.endTime - base) > Number.MAX_SAFE_INTEGER)) throw new Error('Trace duration exceeds safely representable milliseconds.');
    for (const e of events) {
      if (e.attributes['whalesong.error_onset_ms'] !== undefined) e.attributes['whalesong.error_onset_ms'] = errorOnsetOf(e) - base;
      e.startTime -= base; e.endTime -= base;
    }
    const localIds = new Set(events.map(e => e.id)), missingParents = events.filter(e => e.parentId && !localIds.has(e.parentId)).length;
    const traceWarnings = [...warnings];

View on GitHub (pinned to 433685b202)