{"record":{"id":"1aef23db72fc1454","repo":"danny-avila/LibreChat","slug":"checkpoint-too-large","errorCode":"CHECKPOINT_TOO_LARGE","errorMessage":"Checkpoint state is ${mb(bytes)} MB, over the ${mb(limit)} MB limit for a durable pause. This conversation carries too much state to pause for input — large tool outputs or inlined media are the usual cause. Start a new conversation or reduce context.","messagePattern":"Checkpoint state is (.+?) MB, over the (.+?) MB limit for a durable pause\\. This conversation carries too much state to pause for input — large tool outputs or inlined media are the usual cause\\. Start a new conversation or reduce context\\.","errorType":"exception","errorClass":"CheckpointTooLargeError","httpStatus":null,"severity":"critical","filePath":"packages/api/src/agents/checkpointer.ts","lineNumber":490,"sourceCode":"    // prevent. Add the raw metadata's BSON size; the headroom now only has to\n    // cover ids and BSON framing.\n    const [, serializedCheckpoint] = await this.serde.dumpsTyped(checkpoint);\n    const [, serializedMetadata] = await this.serde.dumpsTyped(metadata);\n    const metadataSearchBytes = mongoose.mongo.BSON.calculateObjectSize(\n      metadata as unknown as Record<string, unknown>,\n    );\n    const bytes =\n      serializedCheckpoint.byteLength + serializedMetadata.byteLength + metadataSearchBytes;\n    const threadId = config.configurable?.thread_id as string | undefined;\n    const mb = (n: number): string => (n / 1024 / 1024).toFixed(1);\n    if (bytes > this.hardLimitBytes) {\n      // The anchoring write row was already persisted by `putWrites`; the pre-run prune and Mongo\n      // TTL reclaim it. Drop any parked bookkeeping so it doesn't linger in memory.\n      this.bufferedBookkeeping.delete(checkpoint.id);\n      logger.error(\n        `[checkpointer] HITL checkpoint for thread ${threadId ?? 'unknown'} is ${mb(bytes)} MB, over the ${mb(this.hardLimitBytes)} MB durable-pause limit; refusing the write (a document past 16 MB cannot be stored in MongoDB).`,\n      );\n      throw new CheckpointTooLargeError(bytes, this.hardLimitBytes, threadId);\n    }\n    if (bytes >= this.warnBytes) {\n      logger.warn(\n        `[checkpointer] HITL checkpoint for thread ${threadId ?? 'unknown'} is ${mb(bytes)} MB, past the ${mb(this.warnBytes)} MB soft threshold (hard limit ${mb(this.hardLimitBytes)} MB) — approaching MongoDB's single-document ceiling.`,\n      );\n      return;\n    }\n    logger.debug(\n      `[checkpointer] Persisting HITL checkpoint for thread ${threadId ?? 'unknown'}: ${bytes} bytes`,\n    );\n  }\n}\n\n/**\n * Evict genuinely-stale entries from a fate-tracking map once it is crowded\n * ({@link WRITE_ANCHOR_SWEEP_THRESHOLD}). Entries from a crashed run (older than\n * {@link WRITE_ANCHOR_STALE_MS}) are reclaimed; recent in-flight entries never are.\n */","sourceCodeStart":472,"sourceCodeEnd":508,"githubUrl":"https://github.com/danny-avila/LibreChat/blob/5ff282f9006c436e561de1afd39a481bea1ef0d8/packages/api/src/agents/checkpointer.ts#L472-L508","documentation":"CheckpointTooLargeError (code CHECKPOINT_TOO_LARGE) is thrown by assertCheckpointFitsDocument on the HITL (human-in-the-loop) pause path when the serialized checkpoint + serialized metadata + raw metadata BSON size exceeds hardLimitBytes (the MongoDB 16 MB single-document ceiling). The check exists so an oversize pause fails legibly instead of producing a raw BSONObjectTooLarge from Mongo. The anchoring write row is left for the pre-run prune and TTL to reclaim.","triggerScenarios":"An agent run that pauses for human input where the conversation state — large tool outputs, inlined base64 media, accumulated message history, or metadata.writes holding a big tool result — pushes the checkpoint document past the 16 MB BSON limit.","commonSituations":"Long-running agents that accumulate large file/image attachments; tool calls that return very large JSON; conversations with many rounds where context compaction has not pruned; base64-encoded images stored inline in messages.","solutions":["Start a new conversation/thread once the context grows large rather than pausing an overstuffed one.","Reduce inline media — store attachments out-of-band and reference them by URL/id instead of embedding base64 in the checkpoint.","Enable or tighten context pruning / message windowing so old tool outputs are dropped before pause.","If running a custom checkpointer, raise hardLimitBytes only up to MongoDB's true 16 MB ceiling — there is no headroom above it."],"exampleFix":"// before — agent accumulates a 20 MB tool result then pauses for input\n\n// after — trim large tool outputs before the pause\nconst trimmed = trimToolOutputsToSummaries(messages, { maxBytes: 1_000_000 });\nawait runAgent({ ...state, messages: trimmed });\n// and store large artifacts out-of-band, referencing them by id","handlingStrategy":"validation","validationCode":"// estimate checkpoint size before pausing\nfunction estimateCheckpointBytes(messages: unknown[]): number {\n  return JSON.stringify(messages).length;\n}\nconst HARD_LIMIT = 16 * 1024 * 1024;\nif (estimateCheckpointBytes(state.messages) > HARD_LIMIT * 0.9) {\n  throw new Error('Refusing to pause: checkpoint would exceed MongoDB 16 MB limit');\n}","typeGuard":"function isCheckpointTooLargeError(e: unknown): boolean {\n  return e instanceof Error && (e as { code?: string }).code === 'CHECKPOINT_TOO_LARGE';\n}","tryCatchPattern":"try {\n  await agent.invoke(state, { configurable: { thread_id } });\n} catch (error) {\n  if (isCheckpointTooLargeError(error)) {\n    // surface to the user; offer to start a new conversation\n    return { fatal: true, reason: 'context_too_large_to_pause' };\n  }\n  throw error;\n}","preventionTips":["Store large media out-of-band; never inline base64 in messages.","Enable message-windowing / context pruning so old tool outputs drop before pause.","Summarize large tool results before they enter conversation history.","Start a new thread once context grows large instead of pausing."],"tags":["agents","checkpoint","mongodb","hitl","context-size","langgraph"],"backgroundTag":null,"analyzedSha":"5ff282f9006c436e561de1afd39a481bea1ef0d8","analyzedAt":"2026-08-12T21:38:08.145Z","schemaVersion":2},"datasetVersion":"2026-08-12T23:17:12.415Z"}