Hmbown/CodeWhale · error · Error
Import exceeds the event limit.
Error message
Import exceeds the ${maxEvents.toLocaleString()} event limit. What it means
Import size cap in fromOTLP/ingest: the incoming OTLP document expands to more events than the configured maxEvents limit. The cap bounds memory and compile cost for a single import; the caller must split or trim the trace before importing it.
Solutions
- Split the export into smaller chunks, e.g. by trace, and import each separately.
- Raise options.maxEvents up to the 250000 ceiling if your environment can handle it.
- Filter spans at export time (sampling, time window) to reduce count below the limit.
Example fix
// before
importTrace(text, 'big.json');
// after
importTrace(text, 'big.json', { maxEvents: 250000 }); Defensive patterns
Strategy: validation
Validate before calling
const spanCount = countOtlpSpans(text); // parse and count resourceSpans[].scopeSpans[].spans[]
const maxEvents = 250000;
if (spanCount > maxEvents) throw new Error(`Split export: ${spanCount} spans exceeds ${maxEvents}`); Try / catch
try {
traces = importTrace(text, file, { maxEvents: 250000 });
} catch (e) {
if (e instanceof Error && e.message.includes('event limit')) {
console.error('Split the export by trace and import each chunk separately');
} else throw e;
} Prevention
- Estimate export size/count before importing and split proactively by trace.
- Configure collector sampling to bound span volume.
- Remember the hard ceiling is 250000 events regardless of options.
When it happens
Trigger: Calling the OTLP import (via importTrace) with a document whose span count exceeds maxEvents (default 250000, configurable via ImportOptions.maxEvents within [1, 250000]).
Common situations: Bulk exports from long-running services; a collector dumping every span from a busy hour; forgetting to raise or intentionally cap maxEvents for very large exports.
Understand the failure class
Background: "File too large" / "file size exceeds limit" errors: why libraries cap file sizes and how to fix them — this error's family across 46 libraries.
Related errors
- Import exceeds the event limit, including span events.
- Every OTLP span requires traceId and spanId.
- No spans found in resourceSpans[].scopeSpans[].spans[].
- OTLP span : end precedes start.
- This import contains more than
AI-assisted analysis of Hmbown/CodeWhale@433685b202 (2026-09-15).
Data as JSON: /api/errors/c5ba3bf6ba59f6ee.
Report an issue: GitHub.
Appendix: source
Thrown at pet/src/core/ingest.ts:165
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),
};
}
interface OtlpRecord { span: Obj; resource: Obj; scope: Obj; resourceSchema?: string; scopeSchema?: string }
function otlpRecords(doc: Obj): OtlpRecord[] {
const out: OtlpRecord[] = [];
for (const r of list(doc.resourceSpans)) {
for (const s of list(r.scopeSpans ?? r.instrumentationLibrarySpans)) {
for (const span of list(s.spans)) out.push({ span: obj(span), resource: obj(r.resource), scope: obj(s.scope ?? s.instrumentationLibrary), resourceSchema: r.schemaUrl, scopeSchema: s.schemaUrl });
}
}
return out;
}
function fromOTLP(doc: Obj, maxEvents: number): { events: WhaleEvent[]; origins: Map<string, string>; warnings: string[] } {
const records = otlpRecords(doc), bases = new Map<string, bigint>(), warnings: string[] = [];
if (!records.length) throw new Error('No spans found in resourceSpans[].scopeSpans[].spans[].');
if (records.length > maxEvents) throw new Error(`Import exceeds the ${maxEvents.toLocaleString()} event limit.`);
for (const { span: s } of records) {
if (!str(s.traceId) || !str(s.spanId)) throw new Error('Every OTLP span requires traceId and spanId.');
const start = ns(s.startTimeUnixNano, 'startTimeUnixNano');
const end = s.endTimeUnixNano === undefined ? start : ns(s.endTimeUnixNano, 'endTimeUnixNano');
if (end < start) throw new Error(`OTLP span ${s.spanId}: end precedes start.`);
let earliest = start;
for (const e of list(s.events)) { const t = ns(e.timeUnixNano, 'event.timeUnixNano'); if (t < earliest) earliest = t; }
if (!bases.has(s.traceId) || earliest < bases.get(s.traceId)!) bases.set(s.traceId, earliest);
if ((s.droppedEventsCount ?? 0) > 0) warnings.push(`Span ${s.spanId} reports ${s.droppedEventsCount} dropped events; coverage is incomplete.`);
}
const events: WhaleEvent[] = [];
for (const rec of records) {
const s = rec.span, a = { ...attributes(rec.resource.attributes), ...attributes(s.attributes) };
const origin = bases.get(s.traceId)!, start = ns(s.startTimeUnixNano, 'startTimeUnixNano');
const end = s.endTimeUnixNano === undefined ? start : ns(s.endTimeUnixNano, 'endTimeUnixNano');
const name = String(s.name ?? 'unnamed span');
const e: WhaleEvent = {
schemaVersion: 1, id: s.spanId, traceId: s.traceId, parentId: str(s.parentSpanId),View on GitHub (pinned to 433685b202)