{"record":{"id":"3b8f2687459f5753","repo":"Hmbown/CodeWhale","slug":"the-file-contains-no-events","errorCode":null,"errorMessage":"The file contains no events.","messagePattern":"The file contains no events\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/src/core/ingest.ts","lineNumber":259,"sourceCode":"    trace.events = trace.events.map(e => privacyEvent(e, mode));\n    return [trace];\n  }\n  const records = Array.isArray(safe) ? safe : Array.isArray(root.events) ? root.events : null;\n  if (isCodewhaleRuntimeDocument(records ?? [safe])) {\n    const trace = fromCodewhaleRuntime(records ?? [safe], filename, maxEvents);\n    trace.privacy = mode;\n    trace.events = trace.events.map(e => privacyEvent(e, mode));\n    return [trace];\n  }\n  const isOTLP = Array.isArray(root.resourceSpans);\n  let all: WhaleEvent[], origins = new Map<string, string>(), warnings: string[] = [];\n  if (isOTLP) { const r = fromOTLP(root, maxEvents); all = r.events; origins = r.origins; warnings = r.warnings; }\n  else {\n    const incoming = records ?? [safe];\n    if (incoming.length > maxEvents) throw new Error(`Import exceeds the ${maxEvents.toLocaleString()} event limit.`);\n    all = incoming.map(normalizedEvent);\n  }\n  if (!all.length) throw new Error('The file contains no events.');\n  const groups = new Map<string, WhaleEvent[]>(), ids = new Set<string>();\n  for (const e of all) {\n    const key = `${e.traceId}\\0${e.id}`;\n    if (ids.has(key)) throw new Error(`Duplicate event identity (${e.traceId}, ${e.id}). Import cancelled.`);\n    ids.add(key);\n    const group = groups.get(e.traceId) ?? []; group.push(privacyEvent(e, mode)); groups.set(e.traceId, group);\n    if (groups.size > maxTraces) throw new Error(`This import contains more than ${maxTraces} traces. Split it by trace ID.`);\n  }\n  return [...groups].map(([id, events]) => {\n    events.sort((a, b) => a.startTime - b.startTime || a.id.localeCompare(b.id));\n    const base = isOTLP ? 0 : events[0].startTime;\n    if (!isOTLP && events.some(e => Math.abs(e.endTime - base) > Number.MAX_SAFE_INTEGER)) throw new Error('Trace duration exceeds safely representable milliseconds.');\n    for (const e of events) {\n      if (e.attributes['whalesong.error_onset_ms'] !== undefined) e.attributes['whalesong.error_onset_ms'] = errorOnsetOf(e) - base;\n      e.startTime -= base; e.endTime -= base;\n    }\n    const localIds = new Set(events.map(e => e.id)), missingParents = events.filter(e => e.parentId && !localIds.has(e.parentId)).length;\n    const traceWarnings = [...warnings];","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/src/core/ingest.ts#L241-L277","documentation":"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).","triggerScenarios":"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 [].","commonSituations":"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.","solutions":["Verify the file actually contains event records and uses the expected whalesong/OTLP format.","Re-export with a time range/filter that includes at least one event.","Check normalizedEvent compatibility: field names like traceId, id, startTime must be present in the source records."],"exampleFix":"// before\nimportTrace(JSON.stringify([]));\n// after\nconst doc = JSON.parse(text);\nif (!doc || (Array.isArray(doc) && doc.length === 0)) throw new Error('Export contains no events; widen the export filter.');\nimportTrace(text);","handlingStrategy":"validation","validationCode":"const doc = JSON.parse(text);\nconst hasEvents = Array.isArray(doc) ? doc.length > 0 : Array.isArray(doc.resourceSpans) || doc.events?.length > 0 || true;\nif (!hasEvents) throw new Error('Import contains no events.');","typeGuard":"function hasEvents(doc: unknown): boolean {\n  if (Array.isArray(doc)) return doc.length > 0;\n  if (doc && typeof doc === 'object') {\n    const d = doc as Record<string, unknown>;\n    return Array.isArray(d.resourceSpans) || Array.isArray(d.events);\n  }\n  return false;\n}","tryCatchPattern":"try {\n  importTrace(text);\n} catch (e) {\n  if (e instanceof Error && e.message === 'The file contains no events.') {\n    console.error('The export matched nothing; widen the filter or fix the format.');\n  }\n}","preventionTips":["Verify the export filter matched at least one event before downloading.","Check the file format matches what normalizedEvent/OTLP expects.","Inspect the JSON manually for an empty array or empty span lists.","Confirm the exporter's time range overlaps actual traffic."],"tags":["validation","empty-result","ingest"],"backgroundTag":"empty-result-set","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}