paperclipai/paperclip · error · Error

Source content is ${sourceBytes} bytes, which exceeds the co

Error message

Source content is ${sourceBytes} bytes, which exceeds the configured LLM Wiki source limit of ${maxSourceBytes} bytes.

What it means

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.

Source

Thrown at packages/plugins/plugin-llm-wiki/src/wiki/core.ts:694

  ]);
  return {
    ...base,
    maxCharacters: Math.min(base.maxCharacters, profile.cursor.maxWindowCharacters),
    maxCharactersPerSource: Math.min(base.maxCharactersPerSource, profile.cursor.maxCharactersPerSource),
  };
}

function estimateSourceCostCents(characters: number, costCentsPerThousandSourceCharacters: number): number {
  if (characters <= 0 || costCentsPerThousandSourceCharacters <= 0) return 0;
  return Math.ceil((characters / 1000) * costCentsPerThousandSourceCharacters);
}

async function assertSourceWithinConfiguredLimit(ctx: PluginContext, companyId: string, contents: string) {
  const config = await ctx.config.get(companyId);
  const maxSourceBytes = normalizeMaxSourceBytes(config.maxSourceBytes);
  const sourceBytes = byteLength(contents);
  if (sourceBytes > maxSourceBytes) {
    throw new Error(`Source content is ${sourceBytes} bytes, which exceeds the configured LLM Wiki source limit of ${maxSourceBytes} bytes.`);
  }
}

function normalizeEventIngestionSettings(value: unknown): WikiEventIngestionSettings {
  if (!value || typeof value !== "object" || Array.isArray(value)) {
    return { ...DEFAULT_EVENT_INGESTION_SETTINGS, sources: { ...DEFAULT_EVENT_INGESTION_SETTINGS.sources } };
  }
  const record = value as Record<string, unknown>;
  const sources = record.sources && typeof record.sources === "object" && !Array.isArray(record.sources)
    ? record.sources as Record<string, unknown>
    : {};
  const maxCharacters = typeof record.maxCharacters === "number" && Number.isFinite(record.maxCharacters)
    ? Math.max(1000, Math.min(MAX_EVENT_SOURCE_CHARS, Math.floor(record.maxCharacters)))
    : DEFAULT_EVENT_INGESTION_SETTINGS.maxCharacters;
  return {
    enabled: normalizeBoolean(record.enabled, DEFAULT_EVENT_INGESTION_SETTINGS.enabled),
    sources: {
      issues: normalizeBoolean(sources.issues, DEFAULT_EVENT_INGESTION_SETTINGS.sources.issues),

View on GitHub (pinned to 67001ec6eb)

Solutions

  1. Reduce the content size below maxSourceBytes (split into multiple ingestions, truncate, or summarize).
  2. Raise config.maxSourceBytes for the company (be aware of ingestion cost and LLM context downstream).
  3. Pre-check byteLength(content) before calling the ingest path and chunk if it exceeds the limit.

Example fix

// before
await assertSourceWithinConfiguredLimit(ctx, companyId, hugeContent); // throws if > 250000 bytes
// after
const MAX = 250_000;
if (Buffer.byteLength(hugeContent) > MAX) {
  // chunk or truncate hugeContent
}
await assertSourceWithinConfiguredLimit(ctx, companyId, truncatedContent);
Defensive patterns

Strategy: validation

Validate before calling

function byteLength(s: string): number {
  return typeof Buffer !== "undefined" ? Buffer.byteLength(s) : new TextEncoder().encode(s).length;
}
async function getMax(ctx: PluginContext, companyId: string): Promise<number> {
  const cfg = await ctx.config.get(companyId);
  const max = cfg?.maxSourceBytes;
  return typeof max === "number" && Number.isFinite(max) ? max : 250_000;
}
const max = await getMax(ctx, companyId);
if (byteLength(content) > max) { /* chunk or truncate */ }

Try / catch

try {
  await assertSourceWithinConfiguredLimit(ctx, companyId, content);
} catch (err) {
  if (err instanceof Error && err.message.includes("exceeds the configured LLM Wiki source limit")) {
    // split content, then ingest each chunk separately
  } else throw err;
}

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of paperclipai/paperclip@67001ec6eb (2026-08-12). Data as JSON: /api/errors/e786fca05a13d295. Report an issue: GitHub.