{"record":{"id":"72c58efb811b972d","repo":"Hmbown/CodeWhale","slug":"import-exceeds-the-maxevents-tolocalestring-event-limit-72c58e","errorCode":null,"errorMessage":"Import exceeds the ${maxEvents.toLocaleString()} event limit, including span events.","messagePattern":"Import exceeds the (.+?) event limit, including span events\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/src/core/ingest.ts","lineNumber":212,"sourceCode":"      contextTokens: numericAttr(a['context.tokens']), contextLimit: numericAttr(a['context.limit']),\n      retry: numericAttr(a['retry.count'] ?? a['retry.attempt']), status: otelStatus(s.status),\n      latency: Number(end - start) / 1e6, attributes: a,\n      sourceId: str(a['whalesong.source_id']), targetId: str(a['whalesong.target_id']), targetType: str(a['whalesong.target_type']),\n      links: list(s.links).map(l => ({ traceId: l.traceId, spanId: l.spanId, attributes: attributes(l.attributes) })),\n      payload: a['gen_ai.input.messages'] !== undefined || a['gen_ai.output.messages'] !== undefined ? {\n        request: a['gen_ai.input.messages'], response: a['gen_ai.output.messages'],\n      } : undefined,\n      raw: rec,\n    };\n    events.push(e);\n    for (const [i, record] of list(s.events).entries()) {\n      const ea = attributes(record.attributes), time = Number(ns(record.timeUnixNano, 'event.timeUnixNano') - origin) / 1e6;\n      const ename = String(record.name ?? 'span event');\n      events.push({ schemaVersion: 1, id: `${s.spanId}/event/${i}`, traceId: s.traceId, parentId: s.spanId,\n        startTime: time, endTime: time, agentId: e.agentId, name: ename, category: categoryFor(ename, ea),\n        status: ename === 'exception' ? 'error' : 'unknown', attributes: ea, raw: { event: record, spanId: s.spanId, resource: rec.resource, scope: rec.scope } });\n    }\n    if (events.length > maxEvents) throw new Error(`Import exceeds the ${maxEvents.toLocaleString()} event limit, including span events.`);\n  }\n  return { events, origins: new Map([...bases].map(([k, v]) => [k, v.toString()])), warnings };\n}\n\n/** Parse strictly: malformed lines or duplicate identities never disappear silently. */\nexport function importTrace(text: string, filename = 'Imported trace', options: ImportOptions = {}): Trace[] {\n  const mode = options.privacy ?? 'redact', maxEvents = options.maxEvents ?? 250_000;\n  if (!['redact', 'metadata', 'retain'].includes(mode)) throw new Error('Unknown privacy mode.');\n  const maxTraces = options.maxTraces ?? 8;\n  if (!Number.isInteger(maxEvents) || maxEvents < 1 || maxEvents > 250_000) throw new Error('maxEvents must be in [1, 250000].');\n  if (!Number.isInteger(maxTraces) || maxTraces < 1 || maxTraces > 64) throw new Error('maxTraces must be in [1, 64].');\n  if (new TextEncoder().encode(text).length > (options.maxBytes ?? 64 * 1024 * 1024)) throw new Error('File exceeds the 64 MiB MVP import limit. Split the export by trace.');\n  const trimmed = text.replace(/^\\uFEFF/, '').trim();\n  if (!trimmed) throw new Error('The trace file is empty.');\n  let document: unknown;\n  try { document = JSON.parse(trimmed); }\n  catch {\n    document = trimmed.split(/\\r?\\n/).filter(l => l.trim()).map((line, i) => {","sourceCodeStart":194,"sourceCodeEnd":230,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/src/core/ingest.ts#L194-L230","documentation":"After expanding spans into events, fromOTLP also materializes span events (child records) and re-checks the total event count against maxEvents. If spans plus their span events exceed the cap, the import is rejected — the earlier spans-only check is not sufficient.","triggerScenarios":"Importing an OTLP document whose total events (spans + their events[] entries, each producing a record) grows past maxEvents during the second pass, e.g. spans under the limit individually but each carrying many span events.","commonSituations":"Verbose instrumentation attaching many annotation events per span; exception events on every failed request; exporting one huge trace with thousands of events per span.","solutions":["Split the export by trace or time window so total events (spans + span events) fit under maxEvents.","Reduce span-event volume in the producer (sample annotations, dedupe exception events).","Raise options.maxEvents toward the 250000 maximum if the environment allows it."],"exampleFix":"// before\nimportTrace(otlpJson, 'trace.json');\n// after\nimportTrace(otlpJson, 'trace.json', { maxEvents: 250000, maxTraces: 8 });","handlingStrategy":"validation","validationCode":"const total = countOtlpSpans(text) + countOtlpSpanEvents(text); // spans + all spans[].events[]\nif (total > 250000) throw new Error(`Split export: ${total} events exceeds 250000`);","typeGuard":null,"tryCatchPattern":"try {\n  traces = importTrace(text, file, { maxEvents: 250000 });\n} catch (e) {\n  if (e instanceof Error && e.message.includes('including span events')) {\n    console.error('Too many span events: split by trace or reduce per-span annotations');\n  } else throw e;\n}","preventionTips":["Count spans plus their events when estimating import size — events count too.","Sample or cap span-event annotations in the producer.","Split exports by trace so per-chunk totals stay under the limit."],"tags":["limits","otlp","ingest"],"backgroundTag":"file-size-limit-exceeded","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"}