sindresorhus/is · error · TypeError

Expected value which is `non-negative number`, received valu

Error message

Expected value which is `non-negative number`, received value of type `${is(value)}`.

What it means

Thrown by `assertNonNegativeNumber()` (source/index.ts:1783) when the value is not a number >= 0. Unlike the integer variant, fractional values like 0.5 pass, but negative numbers, `NaN`, non-numbers, and numeric strings fail.

Source

Thrown at source/index.ts:1785

		throw new TypeError(message ?? typeErrorMessage('non-empty string', value));
	}
}

export function assertNonEmptyStringAndNotWhitespace(value: unknown, message?: string): asserts value is string {
	if (!isNonEmptyStringAndNotWhitespace(value)) {
		throw new TypeError(message ?? typeErrorMessage('non-empty string and not whitespace', value));
	}
}

export function assertNonNegativeInteger(value: unknown, message?: string): asserts value is number {
	if (!isNonNegativeInteger(value)) {
		throw new TypeError(message ?? typeErrorMessage('non-negative integer', value));
	}
}

export function assertNonNegativeNumber(value: unknown, message?: string): asserts value is number {
	if (!isNonNegativeNumber(value)) {
		throw new TypeError(message ?? typeErrorMessage('non-negative number', value));
	}
}

// eslint-disable-next-line @typescript-eslint/no-restricted-types
export function assertNull(value: unknown, message?: string): asserts value is null {
	if (!isNull(value)) {
		throw new TypeError(message ?? typeErrorMessage('null', value));
	}
}

// eslint-disable-next-line @typescript-eslint/no-restricted-types
export function assertNullOrUndefined(value: unknown, message?: string): asserts value is null | undefined {
	if (!isNullOrUndefined(value)) {
		throw new TypeError(message ?? typeErrorMessage('null or undefined', value));
	}
}

export function assertNumber(value: unknown, message?: string): asserts value is number {

View on GitHub ↗ (pinned to 7821031c66)

Solutions

  1. Convert with `Number(raw)` and verify it parsed before asserting.
  2. Clamp legitimately-noisy values with `Math.max(0, value)` only if a small negative is a known measurement artifact — otherwise fix the ordering/subtraction bug producing it.
  3. Trace NaN back to its source: an `undefined` operand or failed parse upstream.

Example fix

// before
const duration = start - end; // operands swapped
assert.nonNegativeNumber(duration);
// after
const duration = end - start;
assert.nonNegativeNumber(duration);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof value === 'number' && !Number.isNaN(value) && value >= 0) {
  assert.nonNegativeNumber(value);
}

Type guard

function isNonNegativeNumber(v: unknown): v is number {
  return typeof v === 'number' && !Number.isNaN(v) && v >= 0;
}

Try / catch

try {
  assert.nonNegativeNumber(amount);
} catch (error) {
  if (error instanceof TypeError) {
    // amount is negative, NaN, or not a number — clamp with Math.max(0, n) only if that's semantically correct, otherwise reject
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling `assert.nonNegativeNumber(value)` with a negative result from a subtraction (e.g. `endTime - startTime` with clock skew), `NaN` from parsing failures or `undefined` arithmetic, or a string that was never converted to a number.

Common situations: Duration/price/size calculations that go negative due to ordering bugs or clock adjustments; `Number(value)` on malformed input yielding NaN; amounts read from JSON where the field is a string.

Related errors


AI-assisted analysis of sindresorhus/is@7821031c66 (2026-07-31). Data as JSON: /data/errors/c56093586ac3ea1b.json. Report an issue: GitHub ↗.