can1357/oh-my-pi · error · OmpTypeError

divisor must be non-zero

Error message

divisor must be non-zero

What it means

`divisibleBy` validates its divisor before installing it on the number IR. A divisor that is not a finite number or is exactly 0 makes the constraint unsatisfiable or meaningless, so omptype throws 'divisor must be non-zero' as an OmpTypeError.

Source

Thrown at packages/omptype/src/type.ts:836

	atLeast(this: InternalType, bound: number): InternalType {
		return makeType(withNumericBound(this.ir, "min", bound), this[kSteps], metaOf(this));
	},

	atMost(this: InternalType, bound: number): InternalType {
		return makeType(withNumericBound(this.ir, "max", bound), this[kSteps], metaOf(this));
	},

	moreThan(this: InternalType, bound: number): InternalType {
		return makeType(withNumericBound(this.ir, "min", bound, true), this[kSteps], metaOf(this));
	},

	lessThan(this: InternalType, bound: number): InternalType {
		return makeType(withNumericBound(this.ir, "max", bound, true), this[kSteps], metaOf(this));
	},

	divisibleBy(this: InternalType, divisor: number): InternalType {
		if (this.ir.k !== "number") throw new OmpTypeError(`cannot apply divisibility to ${this.ir.k}`);
		if (!Number.isFinite(divisor) || divisor === 0) throw new OmpTypeError("divisor must be non-zero");
		return makeType({ ...this.ir, divisor }, this[kSteps], metaOf(this));
	},

	positive(this: InternalType): InternalType {
		return makeType(withNumericBound(this.ir, "min", 0, true), this[kSteps], metaOf(this));
	},

	negative(this: InternalType): InternalType {
		return makeType(withNumericBound(this.ir, "max", 0, true), this[kSteps], metaOf(this));
	},

	nonNegative(this: InternalType): InternalType {
		return makeType(withNumericBound(this.ir, "min", 0), this[kSteps], metaOf(this));
	},

	nonPositive(this: InternalType): InternalType {
		return makeType(withNumericBound(this.ir, "max", 0), this[kSteps], metaOf(this));
	},

View on GitHub (pinned to 9690622007)

Solutions

  1. Pass a non-zero finite number: `type('number').divisibleBy(5)`.
  2. Validate the divisor before calling: `Number.isFinite(d) && d !== 0`.
  3. Fix the upstream computation producing 0/Infinity/NaN.

Example fix

// before
const d = getConfig().step; // may be 0
const T = type('number').divisibleBy(d); // throws when d === 0

// after
if (Number.isFinite(d) && d !== 0) {
  const T = type('number').divisibleBy(d);
}
Defensive patterns

Strategy: validation

Validate before calling

function validDivisor(d) {
  return Number.isFinite(d) && d !== 0;
}
if (!validDivisor(config.step)) throw new Error('config.step must be non-zero finite');
const T = type('number').divisibleBy(config.step);

Type guard

function isUsableDivisor(d) {
  return typeof d === 'number' && Number.isFinite(d) && d !== 0;
}

Try / catch

try {
  const T = type('number').divisibleBy(d);
} catch (e) {
  if (e instanceof OmpTypeError && e.message.includes('divisor must be non-zero')) {
    // substitute a safe default divisor
  } else throw e;
}

Prevention

When it happens

Trigger: `type('number').divisibleBy(0)`, `.divisibleBy(Infinity)`, `.divisibleBy(NaN)`, or passing a divisor computed at runtime that can evaluate to 0 (e.g. from config or division by zero upstream).

Common situations: Divisor read from config/env defaulting to 0; arithmetic producing Infinity/NaN (x/0) passed straight into `.divisibleBy`.

Related errors


AI-assisted analysis of can1357/oh-my-pi@9690622007 (2026-08-31). Data as JSON: /api/errors/1e355005e6fae728. Report an issue: GitHub.