pear-devs/pear-desktop · error · TypeError
Positive number expected as fade duration!
Error message
Positive number expected as fade duration!
What it means
VolumeFader.setFadeDuration (also invoked from the constructor via options.fadeDuration) requires the fade length to be a number strictly greater than zero, in milliseconds. Zero, negatives, NaN, strings, or Infinity all throw this TypeError.
Source
Thrown at src/plugins/crossfade/fader.ts:240
/**
* Set fade duration.
* (used for future calls to fadeTo)
*
* @param {Number} fadeDuration - fading length in milliseconds
* @throws {TypeError} if fadeDuration is not a number greater than zero
* @return {Object} VolumeFader instance for chaining
*/
setFadeDuration(fadeDuration: number) {
// If duration is a valid number > 0…
if (!Number.isNaN(fadeDuration) && fadeDuration > 0) {
// Set fade duration
this.fadeDuration = fadeDuration;
// Log setting
this.logger?.('Set fade duration to ' + String(fadeDuration) + ' ms.');
} else {
// Abort and throw an exception
throw new TypeError('Positive number expected as fade duration!');
}
// Return instance for chaining
return this;
}
/**
* Define a new fade and start fading.
*
* @param {Number} targetVolume - level to fade to in the range 0…1
* @param {Function} callback - (optional) function to be called when fade is complete
* @throws {TypeError} if targetVolume is not in the range 0…1
* @return {Object} VolumeFader instance for chaining
*/
fadeTo(targetVolume: number, callback?: () => void) {
// Validate volume and throw if invalid
validateVolumeLevel(targetVolume);
View on GitHub (pinned to 1e2aac5706)
Solutions
- Coerce and validate before passing: `Number.isFinite(d) && d > 0 ? d : 1000`
- If an instant switch is desired, use a tiny positive duration like 1 ms instead of 0
- Parse form/storage input with Number() and default on NaN
Example fix
// before
new VolumeFader(media, { fadeDuration: cfg.crossfadeMs }); // cfg value may be 0/NaN
// after
const d = Number(cfg.crossfadeMs);
new VolumeFader(media, { fadeDuration: Number.isFinite(d) && d > 0 ? d : 1000 }); Defensive patterns
Strategy: validation
Validate before calling
const parseFadeDuration = (v: unknown): number => {
const n = Number(v);
return Number.isFinite(n) && n > 0 ? n : 1000;
}; Type guard
const isPositiveNumber = (v: unknown): v is number => typeof v === 'number' && Number.isFinite(v) && v > 0;
Try / catch
try { fader.setFadeDuration(d); } catch (e) { if (e instanceof TypeError && /fade duration/.test(e.message)) fader.setFadeDuration(1000); else throw e; } Prevention
- Enforce min value (e.g. >=50ms) in the settings UI
- For 'instant switch' semantics use a tiny positive value like 1ms, never 0
- Parse persisted settings with Number() and default on failure
When it happens
Trigger: Passing {fadeDuration: 0} hoping for an instant switch; passing a negative or non-numeric value (e.g. '500' as a string from a form field); a NaN produced by `parseInt(userInput)` on empty input; options.fadeDuration coming from config that is null.
Common situations: User-configurable crossfade duration fields that allow 0 or empty input; config migration leaving undefined/null; durations loaded from storage as strings; unit tests passing 0 to mean 'immediate'.
Related errors
- Expected 'linear', 'logarithmic' or a positive number as fad
- Number between 0 and 1 expected as volume!
- Media element expected!
- plugins.downloader.backend.feedback.video-id-not-found
AI-assisted analysis of pear-devs/pear-desktop@1e2aac5706 (2026-08-27).
Data as JSON: /api/errors/4db9a618f0db6ece.
Report an issue: GitHub.