{"record":{"id":"4db9a618f0db6ece","repo":"pear-devs/pear-desktop","slug":"positive-number-expected-as-fade-duration","errorCode":null,"errorMessage":"Positive number expected as fade duration!","messagePattern":"Positive number expected as fade duration!","errorType":"validation","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"src/plugins/crossfade/fader.ts","lineNumber":240,"sourceCode":"  /**\n   * Set fade duration.\n   * (used for future calls to fadeTo)\n   *\n   * @param {Number} fadeDuration - fading length in milliseconds\n   * @throws {TypeError} if fadeDuration is not a number greater than zero\n   * @return {Object} VolumeFader instance for chaining\n   */\n  setFadeDuration(fadeDuration: number) {\n    // If duration is a valid number > 0…\n    if (!Number.isNaN(fadeDuration) && fadeDuration > 0) {\n      // Set fade duration\n      this.fadeDuration = fadeDuration;\n\n      // Log setting\n      this.logger?.('Set fade duration to ' + String(fadeDuration) + ' ms.');\n    } else {\n      // Abort and throw an exception\n      throw new TypeError('Positive number expected as fade duration!');\n    }\n\n    // Return instance for chaining\n    return this;\n  }\n\n  /**\n   * Define a new fade and start fading.\n   *\n   * @param {Number} targetVolume - level to fade to in the range 0…1\n   * @param {Function} callback - (optional) function to be called when fade is complete\n   * @throws {TypeError} if targetVolume is not in the range 0…1\n   * @return {Object} VolumeFader instance for chaining\n   */\n  fadeTo(targetVolume: number, callback?: () => void) {\n    // Validate volume and throw if invalid\n    validateVolumeLevel(targetVolume);\n","sourceCodeStart":222,"sourceCodeEnd":258,"githubUrl":"https://github.com/pear-devs/pear-desktop/blob/1e2aac5706c870c93ed74ba8727ae8390d3b0fa5/src/plugins/crossfade/fader.ts#L222-L258","documentation":"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.","triggerScenarios":"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.","commonSituations":"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'.","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"],"exampleFix":"// before\nnew VolumeFader(media, { fadeDuration: cfg.crossfadeMs }); // cfg value may be 0/NaN\n\n// after\nconst d = Number(cfg.crossfadeMs);\nnew VolumeFader(media, { fadeDuration: Number.isFinite(d) && d > 0 ? d : 1000 });","handlingStrategy":"validation","validationCode":"const parseFadeDuration = (v: unknown): number => {\n  const n = Number(v);\n  return Number.isFinite(n) && n > 0 ? n : 1000;\n};","typeGuard":"const isPositiveNumber = (v: unknown): v is number =>\n  typeof v === 'number' && Number.isFinite(v) && v > 0;","tryCatchPattern":"try { fader.setFadeDuration(d); } catch (e) { if (e instanceof TypeError && /fade duration/.test(e.message)) fader.setFadeDuration(1000); else throw e; }","preventionTips":["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"],"tags":["crossfade","validation","typeerror","duration","configuration"],"backgroundTag":"invalid-configuration-value","analyzedSha":"1e2aac5706c870c93ed74ba8727ae8390d3b0fa5","analyzedAt":"2026-08-27T20:01:08.614Z","schemaVersion":2},"datasetVersion":"2026-08-28T00:17:15.603Z"}