{"record":{"id":"3fb381baa9f9c462","repo":"openclaw/openclaw","slug":"diff-viewer-html-exceeds-max-decoded-html-bytes","errorCode":null,"errorMessage":"Diff viewer HTML exceeds ${MAX_DECODED_HTML_BYTES} bytes.","messagePattern":"Diff viewer HTML exceeds (.+?) bytes\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"extensions/diffs/src/store.ts","lineNumber":97,"sourceCode":"  constructor(params: {\n    rootDir: string;\n    blobStore: PluginBlobStore<DiffArtifactBlobMetadata>;\n    logger?: PluginLogger;\n    cleanupIntervalMs?: number;\n  }) {\n    this.rootDir = path.resolve(params.rootDir);\n    this.blobStore = params.blobStore;\n    this.logger = params.logger;\n    this.cleanupIntervalMs =\n      params.cleanupIntervalMs === undefined\n        ? DEFAULT_CLEANUP_INTERVAL_MS\n        : Math.max(0, Math.floor(params.cleanupIntervalMs));\n  }\n\n  async createArtifact(params: CreateArtifactParams): Promise<DiffArtifactMeta> {\n    const html = Buffer.from(params.html, \"utf8\");\n    if (html.byteLength > MAX_DECODED_HTML_BYTES) {\n      throw new Error(`Diff viewer HTML exceeds ${MAX_DECODED_HTML_BYTES} bytes.`);\n    }\n    const compressedHtml = await gzipAsync(html);\n    const token = crypto.randomBytes(24).toString(\"hex\");\n    const ttlMs = normalizeTtlMs(params.ttlMs);\n    const metadata: DiffViewerArtifactMetadata = {\n      version: 1,\n      kind: \"viewer\",\n      encoding: \"gzip\",\n      tokenHash: hashToken(token),\n      title: params.title,\n      inputKind: params.inputKind,\n      fileCount: params.fileCount,\n      decodedBytes: html.byteLength,\n      ...(params.context ? { context: params.context } : {}),\n    };\n    const entry = await this.registerUnique(compressedHtml, metadata, ttlMs);\n    this.scheduleCleanup();\n    return viewerEntryToMeta(entry, token);","sourceCodeStart":79,"sourceCodeEnd":115,"githubUrl":"https://github.com/openclaw/openclaw/blob/01804a75319da4b69c9ab98ceaa30477e22b8c0b/extensions/diffs/src/store.ts#L79-L115","documentation":"Thrown by DiffArtifactStore.createArtifact when the UTF-8 byte length of the rendered viewer HTML exceeds MAX_DECODED_HTML_BYTES (64 MiB). This caps the in-memory artifact size before gzip compression and blob storage; the same constant bounds gunzip on read (1371 is checked at write time). A viewer exceeding 64MB decoded would exhaust memory and never load in a browser.","triggerScenarios":"Calling createArtifact (via the diffs tool's artifact rendering path) with HTML whose Buffer.byteLength('utf8') > 64*1024*1024. This follows the patch size guards — a huge patch that passed file-count/line limits but still produced oversized HTML, or a pathological before/after of a very large file.","commonSituations":"A diff just under the 120k-line cap but with heavy syntax highlighting/side-by-side doubling the HTML; a single enormous file in before/after mode; many files each adding navigation/prerender overhead. Typically means upstream limits were skirted.","solutions":["Reduce the diff content that produced the HTML (fewer files, fewer lines, collapse unchanged context).","Split into multiple smaller artifacts.","If before/after, diff a smaller region of the file.","Verify the render target isn't producing both viewer+image HTML redundantly for the same oversized content."],"exampleFix":"// before: one artifact for a giant diff\nawait store.createArtifact({ html: hugeRenderedHtml, ... });\n\n// after: chunk files into multiple artifacts under the limit\nfor (const chunk of chunkFiles(files)) {\n  await store.createArtifact({ html: render(chunk), ... });\n}","handlingStrategy":"validation","validationCode":"import { Buffer } from \"node:buffer\";\nconst MAX = 64 * 1024 * 1024;\nif (Buffer.byteLength(html, \"utf8\") > MAX) {\n  throw new Error(`HTML ${Buffer.byteLength(html)} bytes exceeds ${MAX}`);\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Check Buffer.byteLength(html,'utf8') against 64MiB before createArtifact.","Reduce diff content (files/lines) so rendered HTML stays well under 64MB.","Split large diffs into multiple artifacts.","Collapse unchanged context to halve side-by-side HTML size."],"tags":["diffs","artifact","size-limit","memory","storage"],"backgroundTag":null,"analyzedSha":"01804a75319da4b69c9ab98ceaa30477e22b8c0b","analyzedAt":"2026-08-12T04:37:58.197Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}