laurent22/joplin · warning · JoplinError

downloadLimiter

downloadLimiter

Error message

${this.requestId}: Total bytes stored (${this.totalBytes_}) has exceeded the amount established (${this.maxTotalBytes})

What it means

A JoplinError (ErrorCode.DownloadLimiter) thrown by the totalBytes setter on LimitedDownloadController when the accumulated totalBytes_ has already reached or exceeded maxTotalBytes. It fires on the NEXT write attempt after the limit is hit — the setter checks the previous value before accepting the new one. handleChunk wires this so the in-flight download request is destroyed with the error, halting oversized downloads (used when fetching remote images/resources during sync or preview).

Source

Thrown at packages/lib/downloadController.ts:46

	// counts before the downloaded has finished, so at the end if the totalBytes > maxTotalBytesAllowed
	// it means that imageCount will be higher than the total downloaded during the process
	private imagesCount_ = 0;
	// how many images links the content has
	private imageCountExpected_ = 0;
	private requestId = '';

	private maxTotalBytes = 0;
	public readonly maxImagesCount: number;

	public constructor(maxTotalBytes: number, maxImagesCount: number, requestId: string) {
		this.maxTotalBytes = maxTotalBytes;
		this.maxImagesCount = maxImagesCount;
		this.requestId = requestId;
	}

	public set totalBytes(value: number) {
		if (this.totalBytes_ >= this.maxTotalBytes) {
			throw new JoplinError(`${this.requestId}: Total bytes stored (${this.totalBytes_}) has exceeded the amount established (${this.maxTotalBytes})`, ErrorCode.DownloadLimiter);
		}
		this.totalBytes_ = value;
	}

	public get totalBytes() {
		return this.totalBytes_;
	}

	public set imagesCount(value: number) {
		if (this.imagesCount_ > this.maxImagesCount) {
			throw new JoplinError(`${this.requestId}: Total images to be stored (${this.imagesCount_}) has exceeded the amount established (${this.maxImagesCount})`, ErrorCode.DownloadLimiter);
		}
		this.imagesCount_ = value;
	}

	public get imagesCount() {
		return this.imagesCount_;
	}

View on GitHub (pinned to 2654b33620)

Solutions

  1. Increase maxTotalBytes when constructing the LimitedDownloadController if large downloads are expected.
  2. Reduce the number/size of remote images in the content being synced/rendered.
  3. Handle ErrorCode.DownloadLimiter at the call site to degrade gracefully (skip the image, show a placeholder) instead of failing the whole operation.
  4. Investigate the source if a single resource unexpectedly exceeds the cap.

Example fix

// before
controller.totalBytes += chunk.length; // throws once cap exceeded

// after — handle the limit and destroy the request cleanly
try {
  controller.totalBytes += chunk.length;
} catch (error) {
  request.destroy(error);
}
Defensive patterns

Strategy: try-catch

Validate before calling

// Check the remaining budget before starting a download
if (controller.totalBytes + expectedSize > controller.maxTotalBytes) {
  // skip the download or raise the limit
  return;
}

Type guard

import JoplinError from './JoplinError';
import { ErrorCode } from './errors';
function isDownloadLimitError(e: unknown): e is JoplinError {
  return e instanceof JoplinError && (e as any).code === ErrorCode.DownloadLimiter;
}

Try / catch

try {
  controller.totalBytes += chunk.length;
} catch (error) {
  if (isDownloadLimitError(error)) {
    request.destroy(error); // abort the HTTP download cleanly
    return;
  }
  throw error;
}

Prevention

When it happens

Trigger: Streaming a remote resource (image, attachment) via a chunked download where the running byte total crosses maxTotalBytes. handleChunk's returned callback adds chunk.length to totalBytes; once totalBytes_ >= maxTotalBytes, the next chunk throws DownloadLimiter and request.destroy(error) aborts the HTTP request.

Common situations: Syncing a note whose embedded remote images together exceed the configured byte cap; a malicious or misconfigured server returning an oversized body; legitimate large attachments on a target with a low maxTotalBytes setting.

Related errors


AI-assisted analysis of laurent22/joplin@2654b33620 (2026-08-12). Data as JSON: /api/errors/6859bf4f1d7a332f. Report an issue: GitHub.