eyaltoledano/claude-task-master · error

expectedTotal cannot be negative

Error message

expectedTotal cannot be negative

What it means

StreamParser validates that expectedTotal, the expected number of items used for progress estimation, is not negative. A negative value would corrupt percentage calculations and progress reporting. The check runs synchronously in the constructor's validate() step.

Source

Thrown at src/utils/stream-parser.js:65

		this.itemValidator =
			config.itemValidator || StreamParserConfig.defaultItemValidator;
		this.maxBufferSize = config.maxBufferSize || DEFAULT_MAX_BUFFER_SIZE;

		this.validate();
	}

	validate() {
		if (!this.jsonPaths || !Array.isArray(this.jsonPaths)) {
			throw new Error('jsonPaths is required and must be an array');
		}
		if (this.jsonPaths.length === 0) {
			throw new Error('jsonPaths array cannot be empty');
		}
		if (this.maxBufferSize <= 0) {
			throw new Error('maxBufferSize must be positive');
		}
		if (this.expectedTotal < 0) {
			throw new Error('expectedTotal cannot be negative');
		}
		if (this.estimateTokens && typeof this.estimateTokens !== 'function') {
			throw new Error('estimateTokens must be a function');
		}
		if (this.onProgress && typeof this.onProgress !== 'function') {
			throw new Error('onProgress must be a function');
		}
		if (this.onError && typeof this.onError !== 'function') {
			throw new Error('onError must be a function');
		}
		if (
			this.fallbackItemExtractor &&
			typeof this.fallbackItemExtractor !== 'function'
		) {
			throw new Error('fallbackItemExtractor must be a function');
		}
		if (this.itemValidator && typeof this.itemValidator !== 'function') {
			throw new Error('itemValidator must be a function');

View on GitHub (pinned to c0c98d367c)

Solutions

  1. Pass 0 or a positive integer for expectedTotal.
  2. Clamp computed values: expectedTotal: Math.max(0, computedTotal).
  3. Omit expectedTotal if the total is unknown.

Example fix

// before
new StreamParser({ jsonPaths: ['$.items'], expectedTotal: items.length - processed })
// after
new StreamParser({ jsonPaths: ['$.items'], expectedTotal: Math.max(0, items.length - processed) })
Defensive patterns

Strategy: validation

Validate before calling

function assertExpectedTotal(t) {
  if (t !== undefined && (!(Number.isInteger(t)) || t < 0)) {
    throw new RangeError(`expectedTotal must be a non-negative integer, got ${t}`);
  }
  return t;
}
new StreamParser({ ...options, expectedTotal: assertExpectedTotal(options.expectedTotal) });

Type guard

function isNonNegativeInt(v) {
  return typeof v === 'number' && Number.isInteger(v) && v >= 0;
}

Try / catch

try {
  const parser = new StreamParser(options);
} catch (err) {
  if (err.message === 'expectedTotal cannot be negative') {
    options.expectedTotal = Math.max(0, options.expectedTotal);
    return new StreamParser(options);
  }
  throw err;
}

Prevention

When it happens

Trigger: new StreamParser({ jsonPaths: [...], expectedTotal: -1 }) or computing expectedTotal from a length/size expression that underflows (e.g. someArray.length - extra where extra > length).

Common situations: Doing arithmetic like total - alreadyProcessed without clamping to 0; initializing a counter with -1 as a 'sentinel' and passing it straight into the constructor.

Understand the failure class

Background: "Invalid configuration value" and "Unsupported/Unknown setting value" errors: why libraries reject your config strings, numbers, and types — this error's family across 30 libraries.

Related errors


AI-assisted analysis of eyaltoledano/claude-task-master@c0c98d367c (2026-08-29). Data as JSON: /api/errors/3a4f75c99e54e9ab. Report an issue: GitHub.