{"record":{"id":"b2ebf0858e2db32d","repo":"hcengineering/platform","slug":"blob-size-exceeds-limit-of-30mb","errorCode":null,"errorMessage":"Blob size exceeds limit of 30MB","messagePattern":"Blob size exceeds limit of 30MB","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/indexer/src/indexer/indexer.ts","lineNumber":1143,"sourceCode":"    if (docInfo !== undefined && docInfo.size < 30 * 1024 * 1024) {\n      // We have blob, we need to decode it to string.\n      const contentType = (docInfo.contentType ?? defaultContentType).split(';')[0]\n\n      const ct = contentType.toLocaleLowerCase()\n      if ((ct.includes('text/') && contentType !== 'text/rtf') || ct.includes('application/vnd.github.version.diff')) {\n        await this.handleTextBlob(ctx, docInfo, indexedDoc)\n      } else if (isBlobAllowed(contentType)) {\n        await this.handleBlob(ctx, docInfo, indexedDoc)\n      }\n    }\n  }\n\n  private async handleBlob (ctx: MeasureContext<any>, docInfo: Blob | undefined, indexedDoc: IndexedDoc): Promise<void> {\n    if (docInfo !== undefined) {\n      const contentType = (docInfo.contentType ?? '').split(';')[0]\n\n      if (docInfo.size > 30 * 1024 * 1024) {\n        throw new Error('Blob size exceeds limit of 30MB')\n      }\n      const buffer = Buffer.concat(\n        await ctx.with('fetch', {}, (ctx) => this.storageAdapter?.read(ctx, this.workspace, docInfo._id))\n      )\n      let textContent = await ctx.with(\n        'to-text',\n        {},\n        (ctx) => this.contentAdapter.content(ctx, this.workspace.uuid, docInfo._id, contentType, buffer),\n        {\n          workspace: this.workspace.uuid,\n          blobId: docInfo._id,\n          contentType\n        }\n      )\n      textContent = textContent\n        .split(/ +|\\t+|\\f+/)\n        .filter((it) => it)\n        .join(' ')","sourceCodeStart":1125,"sourceCodeEnd":1161,"githubUrl":"https://github.com/hcengineering/platform/blob/63e28dc96483967b2fc21c881b3f1023c1de7718/server/indexer/src/indexer/indexer.ts#L1125-L1161","documentation":"FullTextIndexPipeline.handleBlob refuses to index any attachment whose size exceeds 30MB (30 * 1024 * 1024 bytes). Full-text extraction of very large blobs would exhaust memory/time, so the pipeline throws instead of downloading and converting the blob.","triggerScenarios":"Indexing a document whose attached blob (docInfo.size from the blob metadata) is larger than 31457280 bytes — e.g. large videos, CAD files, big PDFs, disk images uploaded to the workspace and picked up by the full-text indexing pipeline.","commonSituations":"Workspace contains large media uploads that were never meant to be text-indexed, an indexer re-scanning old documents after upload limits were changed, or blob metadata misreporting sizes (or a wrongly matched docInfo).","solutions":["Exclude or skip large blobs from full-text indexing (filter by contentType/size before the pipeline processes them).","Raise the limit only if infrastructure allows, and re-evaluate memory headroom: change the 30 * 1024 * 1024 threshold in indexer.ts.","Wrap handleBlob in a catch that logs and marks the doc as 'skipped-oversize' instead of failing the whole pipeline.","Ensure blob metadata (docInfo.size/contentType) is correct; a wrong match may point at an unrelated huge blob."],"exampleFix":"// before\nif (docInfo.size > 30 * 1024 * 1024) {\n  throw new Error('Blob size exceeds limit of 30MB')\n}\n\n// after\nif (docInfo.size > 30 * 1024 * 1024) {\n  ctx.warn('skipping oversize blob', { _id: docInfo._id, size: docInfo.size })\n  indexedDoc.skipIndex = true\n  return\n}","handlingStrategy":"validation","validationCode":"const MAX_INDEXABLE_BLOB = 30 * 1024 * 1024\n// before indexing (or before upload, if you want to reject early)\nif (docInfo != null && docInfo.size > MAX_INDEXABLE_BLOB) {\n  skipIndexing(docInfo._id, 'oversize')\n}","typeGuard":"function isIndexableBlob (docInfo: Blob | undefined | null): docInfo is Blob {\n  return docInfo != null && docInfo.size <= 30 * 1024 * 1024\n}","tryCatchPattern":"try {\n  await pipeline.index(ctx, doc)\n} catch (err) {\n  if (err.message.includes('Blob size exceeds limit')) {\n    ctx.warn('skipping oversize blob', { docId: doc._id })\n    markSkipped(doc._id, 'oversize')\n  } else {\n    throw err\n  }\n}","preventionTips":["Filter candidate blobs by size/contentType before feeding the indexing pipeline.","Track skipped-oversize documents so they can be handled (OCR/external indexing) later.","Enforce upload size policies at ingestion so index-time surprises are rare.","If the 30MB limit is too low for your workload, adjust it consciously with memory budgeting."],"tags":["indexing","blob","size-limit","full-text-search"],"backgroundTag":"blob-size-limit-exceeded","analyzedSha":"63e28dc96483967b2fc21c881b3f1023c1de7718","analyzedAt":"2026-08-29T15:21:27.377Z","schemaVersion":2},"datasetVersion":"2026-08-29T17:17:51.833Z"}