pear-devs/pear-desktop · error · TypeError

Number between 0 and 1 expected as volume!

Error message

Number between 0 and 1 expected as volume!

What it means

The VolumeFader crossfade helper validates every volume level and throws a TypeError when the value is not a finite number in the inclusive range 0..1. HTMLMediaElement.volume only accepts 0..1, so the fader enforces that contract up front. It is thrown from the constructor (via options.initialVolume) and from fadeTo(targetVolume).

Source

Thrown at src/plugins/crossfade/fader.ts:25

 * - requestAnimationFrame()
 * - ES6
 *
 * Does not depend on any third-party library.
 *
 * License: MIT
 *
 * Nick Schwarzenberg
 * v0.2.0, 07/2016
 */

// Internal utility: check if value is a valid volume level and throw if not
const validateVolumeLevel = (value: number) => {
  // Number between 0 and 1?
  if (!Number.isNaN(value) && value >= 0 && value <= 1) {
    // Yup, that's fine
  } else {
    // Abort and throw an exception
    throw new TypeError('Number between 0 and 1 expected as volume!');
  }
};

type VolumeLogger = <Params extends unknown[]>(
  message: string,
  ...args: Params
) => void;
interface VolumeFaderOptions {
  /**
   * logging `function(stuff, …)` for execution information (default: no logging)
   */
  logger?: VolumeLogger;
  /**
   * either 'linear', 'logarithmic' or a positive number in dB (default: logarithmic)
   */
  fadeScaling?: string | number;
  /**
   * media volume 0…1 to apply during setup (volume not touched by default)

View on GitHub (pinned to 1e2aac5706)

Solutions

  1. Normalize percentages: `fadeTo(userVolume / 100)`
  2. Validate user settings before constructing: clamp with `Math.min(1, Math.max(0, Number(v)))` and check Number.isFinite
  3. If loading volume from persistence, wrap parsing in try/catch and fall back to a sane default like 0.7
  4. Enable strict TypeScript typing (volume: number in 0..1) or a branded type so bad values fail at compile time

Example fix

// before
fader.fadeTo(volumePercent); // 0..100 -> throws

// after
fader.fadeTo(Math.min(1, Math.max(0, volumePercent / 100)));
Defensive patterns

Strategy: validation

Validate before calling

const toVolume = (v: unknown): number => {
  const n = Number(v);
  if (!Number.isFinite(n)) return 0.7; // default
  return Math.min(1, Math.max(0, n));
};
// use: fader.fadeTo(toVolume(userValue));

Type guard

const isValidVolume = (v: unknown): v is number =>
  typeof v === 'number' && Number.isFinite(v) && v >= 0 && v <= 1;

Try / catch

try { fader.fadeTo(target); } catch (e) { if (e instanceof TypeError && /volume/.test(e.message)) { /* clamp and retry */ fader.fadeTo(0); } else throw e; }

Prevention

When it happens

Trigger: Passing options.initialVolume outside 0..1 to `new VolumeFader(media, {initialVolume: 1.5})`, calling fadeTo(-0.1), fadeTo(2), or passing a string/NaN/undefined volume because of a missing argument or a bad computation (e.g. percentage not divided by 100).

Common situations: Storing volume as a 0-100 percentage and forgetting to divide by 100; reading volume from localStorage/settings and parsing it into NaN; defaults like `options.volume ?? 2`; passing dB values instead of linear amplitude.

Related errors


AI-assisted analysis of pear-devs/pear-desktop@1e2aac5706 (2026-08-27). Data as JSON: /api/errors/5ca9fbcd8cf2491c. Report an issue: GitHub.