sindresorhus/is · error · TypeError

Expected value which is `positive integer`, received value o

Error message

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

What it means

Thrown by `assert.positiveInteger()` when the value is not an integer strictly greater than zero. Both conditions are checked at runtime: non-numbers, floats, zero, negative integers, NaN, and Infinity all fail. Used to guard counts, sizes, IDs, and limits that must be whole and positive.

Source

Thrown at source/index.ts:1842

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

export function assertOddInteger(value: number, message?: string): asserts value is number {
	if (!isOddInteger(value)) {
		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));

View on GitHub ↗ (pinned to 7821031c66)

Solutions

  1. If zero is legitimately valid in your domain, use `assert.integer()` plus a `>= 0` check (or the library's non-negative variant) instead.
  2. Convert string inputs with `Number.parseInt(raw, 10)` before asserting, and handle NaN from failed parses.
  3. Apply a floor/default before asserting: `const limit = Math.max(1, Math.trunc(requested))`.
  4. Trace where 0 or a negative slipped in — often an empty collection or an uninitialized counter.

Example fix

// before
const limit = Number(req.query.limit); // '0' or undefined → 0 or NaN
assert.positiveInteger(limit);
// after
const limit = Math.max(1, Number.parseInt(req.query.limit ?? '10', 10) || 10);
assert.positiveInteger(limit);
Defensive patterns

Strategy: validation

Validate before calling

if (!Number.isInteger(value) || value <= 0) {
  throw new RangeError(`Expected positive integer, got ${value}`);
}

Type guard

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

Try / catch

try {
  ow(value, ow.number.positive.integer);
} catch (error) {
  if (error instanceof ArgumentError) {
    throw new RangeError(`Count/size must be a positive integer: ${error.message}`);
  }
  throw error;
}

Prevention

When it happens

Trigger: Calling `assert.positiveInteger(value)` with 0 (zero is not positive), -1, 2.5, NaN, Infinity, a numeric string like '5', or undefined for an unset parameter.

Common situations: Pagination/limit parameters arriving as strings from query strings; a default of 0 used where a minimum of 1 is required; array-length math producing 0 for empty inputs; NaN from parsing a missing env var like `Number(process.env.WORKERS)`.

Related errors


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