pear-devs/pear-desktop · error · Error

plugins.downloader.backend.feedback.video-id-not-found

Error message

plugins.downloader.backend.feedback.video-id-not-found

What it means

The downloader plugin's downloadSong accepts either a YouTube video ID or URL. When the input is not an ID-shaped string, it runs it through getVideoId(); if that cannot extract a video ID from the URL, it throws this localized 'video ID not found' error before any network fetch happens.

Source

Thrown at src/plugins/downloader/main/index.ts:353

) {
  const sendFeedback = (message: unknown, progress?: number) => {
    if (!playlistFolder) {
      sendFeedback_(win, message);
      if (progress && !isNaN(progress)) {
        win.setProgressBar(progress);
      }
    }
  };

  sendFeedback(t('plugins.downloader.backend.feedback.downloading'), 2);

  let id: string | null;
  if (isId) {
    id = idOrUrl;
  } else {
    id = getVideoId(idOrUrl);
    if (typeof id !== 'string')
      throw new Error(
        t('plugins.downloader.backend.feedback.video-id-not-found'),
      );
  }

  let info: YTMusic.TrackInfo | YT.VideoInfo = await yt.music.getInfo(id);

  if (!info) {
    throw new Error(
      t('plugins.downloader.backend.feedback.video-id-not-found'),
    );
  }

  const metadata = getMetadata(info);
  if (metadata.album === 'N/A') {
    metadata.album = '';
  }

  metadata.trackId = trackId;

View on GitHub (pinned to 1e2aac5706)

Solutions

  1. Verify the input is a valid YouTube watch/music/shorts URL or an 11-char ID before calling downloadSong
  2. Trim the input and reject empty strings in the UI layer
  3. Update the downloader plugin / youtube-ext dependency so getVideoId understands current YouTube URL shapes
  4. If you already have the ID, pass it directly (isId path) instead of a URL

Example fix

// before
await downloader.downloadSong userInput);

// after
const trimmed = userInput.trim();
if (!/^[\w-]{11}$/.test(trimmed) && !/youtube\.com|youtu\.be/.test(trimmed)) {
  return notify('Please paste a valid YouTube link or ID');
}
await downloader.downloadSong(trimmed);
Defensive patterns

Strategy: validation

Validate before calling

const YT_URL = /(?:youtube\.com|youtu\.be|youtube\.googleapis\.com)/;
const isUsable = (s: string) =>
  /^[\w-]{11}$/.test(s.trim()) || YT_URL.test(s.trim());

Type guard

const isYouTubeIdOrUrl = (s: string): s is string =>
  /^[\w-]{11}$/.test(s) || /(?:youtube\.com\/watch|youtu\.be\/|youtube\.com\/shorts\/)/.test(s);

Try / catch

try { await downloadSong(input); } catch (e) { if (t('plugins.downloader.backend.feedback.video-id-not-found') === e.message || /video-id-not-found/.test(e.message)) notify('Invalid YouTube link'); else throw e; }

Prevention

When it happens

Trigger: Passing a malformed or non-YouTube URL (e.g. a Spotify/SoundCloud link, a truncated youtube.com URL, a playlist-only URL without v= param); passing a string that neither matches the ID pattern nor parses as a video URL; URLs with extra whitespace or unicode characters that break the parser.

Common situations: Users pasting links from other platforms into the download box; clipboard truncation; YouTube URL format changes (e.g. shorts/music smart URLs) not handled by the installed youtube-ext version; passing an empty string.

Related errors


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