n8n-io/n8n · error · InvalidConcurrencyLimitError

Concurrency limit set to invalid value

Error message

Concurrency limit set to invalid value

What it means

Thrown by `ConcurrencyControlService.normaliseLimit()` when a configured concurrency limit equals exactly `0`. The service treats `0` as an illegal value (it would block all executions), `-1` as unlimited, and any positive integer as a hard cap; values below `-1` are clamped to `-1`. It fires during DI construction (from `globalConfig.executions.concurrency.productionLimit`/`evaluationLimit`) or on lazy eval-queue resolution.

Source

Thrown at packages/cli/src/concurrency/concurrency-control.service.ts:101

			this.queues.set('evaluation', queue);
			this.wireQueue(queue, 'evaluation');
			this.evalQueueResolved = true;
		}

		this.isEnabled = this.queues.size > 0;

		this.limits.forEach((limit, type) => {
			if (type === 'evaluation' && !this.evalQueueResolved) return;
			this.logger.debug(
				`${type === 'production' ? 'Production' : 'Evaluation'} execution concurrency is ${
					limit === -1 ? 'unlimited' : 'limited to ' + limit.toString()
				}`,
			);
		});
	}

	private normaliseLimit(limit: number): number {
		if (limit === 0) throw new InvalidConcurrencyLimitError(0);
		return limit < -1 ? -1 : limit;
	}

	/**
	 * Resolve the evaluation concurrency cap lazily on first use when the
	 * constructor couldn't determine it from the env config alone. The
	 * resolver follows env override → license-tier default; the license is
	 * not guaranteed active at DI-construction time, so we defer until the
	 * first eval execution hits `throttle`. Idempotent; subsequent calls
	 * are a no-op.
	 */
	private ensureEvalQueueResolved(): void {
		if (this.evalQueueResolved) return;
		this.evalQueueResolved = true;

		if (this.globalConfig.executions.mode === 'queue') return;

		const normalised = this.normaliseLimit(

View on GitHub (pinned to 5ac6606e81)

Solutions

  1. Set the limit to a positive integer (e.g. `N8N_CONCURRENCY_PRODUCTION_LIMIT=5`), or `-1` for unlimited.
  2. Remove the env var entirely to fall back to the license-tier default.
  3. Search deployment manifests and `.env` files for any `=0` concurrency setting.

Example fix

# before
N8N_CONCURRENCY_PRODUCTION_LIMIT=0
# after
N8N_CONCURRENCY_PRODUCTION_LIMIT=5
Defensive patterns

Strategy: validation

Validate before calling

function validateLimit(name: string, v: number) {
  if (v === 0) throw new Error(`${name} must be > 0 or -1 (unlimited); got 0`);
  return v < -1 ? -1 : v;
}

Prevention

When it happens

Trigger: Setting `N8N_CONCURRENCY_PRODUCTION_LIMIT=0` or `N8N_CONCURRENCY_EVALUATION_LIMIT=0`; passing 0 programmatically through GlobalConfig; a config layer defaulting to 0 due to a bad env parse.

Common situations: Operator misunderstands 0 as 'disabled' instead of 'blocked'; env var set to an empty string that parses to 0; migration from an older config schema that used 0 to mean unlimited.

Related errors


AI-assisted analysis of n8n-io/n8n@5ac6606e81 (2026-08-12). Data as JSON: /api/errors/e022cad497967e01. Report an issue: GitHub.