{"record":{"id":"e786fca05a13d295","repo":"paperclipai/paperclip","slug":"source-content-is-sourcebytes-bytes-which-exce","errorCode":null,"errorMessage":"Source content is ${sourceBytes} bytes, which exceeds the configured LLM Wiki source limit of ${maxSourceBytes} bytes.","messagePattern":"Source content is (.+?) bytes, which exceeds the configured LLM Wiki source limit of (.+?) bytes\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/plugins/plugin-llm-wiki/src/wiki/core.ts","lineNumber":694,"sourceCode":"  ]);\n  return {\n    ...base,\n    maxCharacters: Math.min(base.maxCharacters, profile.cursor.maxWindowCharacters),\n    maxCharactersPerSource: Math.min(base.maxCharactersPerSource, profile.cursor.maxCharactersPerSource),\n  };\n}\n\nfunction estimateSourceCostCents(characters: number, costCentsPerThousandSourceCharacters: number): number {\n  if (characters <= 0 || costCentsPerThousandSourceCharacters <= 0) return 0;\n  return Math.ceil((characters / 1000) * costCentsPerThousandSourceCharacters);\n}\n\nasync function assertSourceWithinConfiguredLimit(ctx: PluginContext, companyId: string, contents: string) {\n  const config = await ctx.config.get(companyId);\n  const maxSourceBytes = normalizeMaxSourceBytes(config.maxSourceBytes);\n  const sourceBytes = byteLength(contents);\n  if (sourceBytes > maxSourceBytes) {\n    throw new Error(`Source content is ${sourceBytes} bytes, which exceeds the configured LLM Wiki source limit of ${maxSourceBytes} bytes.`);\n  }\n}\n\nfunction normalizeEventIngestionSettings(value: unknown): WikiEventIngestionSettings {\n  if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n    return { ...DEFAULT_EVENT_INGESTION_SETTINGS, sources: { ...DEFAULT_EVENT_INGESTION_SETTINGS.sources } };\n  }\n  const record = value as Record<string, unknown>;\n  const sources = record.sources && typeof record.sources === \"object\" && !Array.isArray(record.sources)\n    ? record.sources as Record<string, unknown>\n    : {};\n  const maxCharacters = typeof record.maxCharacters === \"number\" && Number.isFinite(record.maxCharacters)\n    ? Math.max(1000, Math.min(MAX_EVENT_SOURCE_CHARS, Math.floor(record.maxCharacters)))\n    : DEFAULT_EVENT_INGESTION_SETTINGS.maxCharacters;\n  return {\n    enabled: normalizeBoolean(record.enabled, DEFAULT_EVENT_INGESTION_SETTINGS.enabled),\n    sources: {\n      issues: normalizeBoolean(sources.issues, DEFAULT_EVENT_INGESTION_SETTINGS.sources.issues),","sourceCodeStart":676,"sourceCodeEnd":712,"githubUrl":"https://github.com/paperclipai/paperclip/blob/67001ec6eb96ae601aa27bc91d9b2415d665334a/packages/plugins/plugin-llm-wiki/src/wiki/core.ts#L676-L712","documentation":"Thrown by assertSourceWithinConfiguredLimit() when the byte length of source content about to be ingested exceeds the configured maxSourceBytes (default DEFAULT_MAX_SOURCE_BYTES = 250000, overridable via config.maxSourceBytes). The actual byte count and the limit are both interpolated. The check uses byteLength() (raw bytes, not characters), so multi-byte content is measured correctly.","triggerScenarios":"Ingesting a large source document, log dump, or concatenated event payload whose UTF-8 byte size exceeds maxSourceBytes. Default 250000 bytes (~250KB) exceeded by a single big file or by aggregating many events.","commonSituations":"Ingesting a repo README plus attached logs. Bulk event ingestion that concatenates many records into one source. maxSourceBytes not tuned for the workload. Unicode-heavy content where character count under-represents byte count.","solutions":["Reduce the content size below maxSourceBytes (split into multiple ingestions, truncate, or summarize).","Raise config.maxSourceBytes for the company (be aware of ingestion cost and LLM context downstream).","Pre-check byteLength(content) before calling the ingest path and chunk if it exceeds the limit."],"exampleFix":"// before\nawait assertSourceWithinConfiguredLimit(ctx, companyId, hugeContent); // throws if > 250000 bytes\n// after\nconst MAX = 250_000;\nif (Buffer.byteLength(hugeContent) > MAX) {\n  // chunk or truncate hugeContent\n}\nawait assertSourceWithinConfiguredLimit(ctx, companyId, truncatedContent);","handlingStrategy":"validation","validationCode":"function byteLength(s: string): number {\n  return typeof Buffer !== \"undefined\" ? Buffer.byteLength(s) : new TextEncoder().encode(s).length;\n}\nasync function getMax(ctx: PluginContext, companyId: string): Promise<number> {\n  const cfg = await ctx.config.get(companyId);\n  const max = cfg?.maxSourceBytes;\n  return typeof max === \"number\" && Number.isFinite(max) ? max : 250_000;\n}\nconst max = await getMax(ctx, companyId);\nif (byteLength(content) > max) { /* chunk or truncate */ }","typeGuard":null,"tryCatchPattern":"try {\n  await assertSourceWithinConfiguredLimit(ctx, companyId, content);\n} catch (err) {\n  if (err instanceof Error && err.message.includes(\"exceeds the configured LLM Wiki source limit\")) {\n    // split content, then ingest each chunk separately\n  } else throw err;\n}","preventionTips":["Pre-measure byte length (not char length) of source content.","Chunk large inputs before ingestion.","Tune config.maxSourceBytes to the workload if justified by downstream LLM context."],"tags":["llm-wiki","ingest","size-limit","paperclip"],"backgroundTag":null,"analyzedSha":"67001ec6eb96ae601aa27bc91d9b2415d665334a","analyzedAt":"2026-08-12T12:05:45.408Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}