sindresorhus/is · error · TypeError

Expected value which is `positive number`, received value of

Error message

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

What it means

Thrown by `assert.positiveNumber()` when the value is not a number strictly greater than zero. Unlike `positiveInteger`, fractional values are allowed, but 0, negatives, NaN, and non-numbers fail. Guards quantities like durations, rates, prices, and dimensions that must be positive.

Source

Thrown at source/index.ts:1848

		throw new TypeError(message ?? typeErrorMessage('odd integer', value));
	}
}

export function assertPlainObject<Value = unknown>(value: unknown, message?: string): asserts value is Record<PropertyKey, Value> {
	if (!isPlainObject(value)) {
		throw new TypeError(message ?? typeErrorMessage('plain object', value));
	}
}

export function assertPositiveInteger(value: unknown, message?: string): asserts value is number {
	if (!isPositiveInteger(value)) {
		throw new TypeError(message ?? typeErrorMessage('positive integer', value));
	}
}

export function assertPositiveNumber(value: unknown, message?: string): asserts value is number {
	if (!isPositiveNumber(value)) {
		throw new TypeError(message ?? typeErrorMessage('positive number', value));
	}
}

export function assertPrimitive(value: unknown, message?: string): asserts value is Primitive {
	if (!isPrimitive(value)) {
		throw new TypeError(message ?? typeErrorMessage('primitive', value));
	}
}

export function assertPromise<T = unknown>(value: unknown, message?: string): asserts value is Promise<T> {
	if (!isPromise(value)) {
		throw new TypeError(message ?? typeErrorMessage('Promise', value));
	}
}

export function assertPropertyKey(value: unknown, message?: string): asserts value is PropertyKey {
	if (!isPropertyKey(value)) {
		throw new TypeError(message ?? typeErrorMessage('PropertyKey', value));

View on GitHub ↗ (pinned to 7821031c66)

Solutions

  1. Check whether 0 should be allowed in your domain; if so use `assert.number()` with an explicit `>= 0` check.
  2. Guard against NaN at the parse site: `const n = Number(raw); if (Number.isNaN(n)) throw new Error('invalid <field>')`.
  3. Convert string inputs to numbers before asserting.
  4. Add a domain-specific minimum/default before the assert instead of letting 0 reach it.

Example fix

// before
const timeout = Number(config.timeout); // config.timeout = 'fast' → NaN
assert.positiveNumber(timeout);
// after
const parsed = Number(config.timeout);
const timeout = Number.isFinite(parsed) && parsed > 0 ? parsed : 5000;
assert.positiveNumber(timeout);
Defensive patterns

Strategy: validation

Validate before calling

if (typeof value !== 'number' || Number.isNaN(value) || value <= 0) {
  throw new RangeError(`Expected positive number, got ${value}`);
}

Type guard

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

Try / catch

try {
  ow(value, ow.number.positive);
} catch (error) {
  if (error instanceof ArgumentError) {
    throw new RangeError(`Value must be greater than zero: ${error.message}`);
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling `assert.positiveNumber(value)` with 0, a negative number, NaN (e.g. from `Number('abc')`), a numeric string, null, or undefined. Note that `Infinity` is a positive number and passes.

Common situations: Timeout or interval values defaulting to 0; price/quantity computed from a subtraction going negative; NaN propagating from a failed string-to-number conversion in config or user input; unit mixups producing 0 after truncation.

Related errors


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