Débogage6 min de lecture

Comment corriger ERR_INVALID_URL dans Node.js

L'erreur ERR_INVALID_URL dans Node.js se produit lorsque le constructeur URL ou url.parse() reçoit une chaîne qui n'est pas une URL valide. Les causes fréquentes sont l'absence de protocole, des caractères spéciaux non encodés et un encodage pour cent incorrect. Corrigez-la en validant l'entrée et en encodant les caractères spéciaux avant l'analyse.

Quelles sont les causes de ERR_INVALID_URL ?

L'erreur ERR_INVALID_URL (formellement TypeError [ERR_INVALID_URL]: Invalid URL) est levée par Node.js lorsque le constructeur URL ou la fonction héritée url.parse() reçoit une chaîne qui ne peut pas être analysée comme une URL valide. Cette erreur est fréquente lors du traitement d'une entrée utilisateur, de l'analyse de fichiers de configuration ou de la manipulation d'URL provenant de sources externes.

Le constructeur URL suit le standard WHATWG URL, qui est plus strict que l'ancienne analyse basée sur les RFC. Une chaîne doit comporter un schéma valide (comme https:), une autorité valide (nom d'hôte) ainsi que des composants de chemin et de requête correctement formatés pour être acceptée comme une URL valide.

// Ceci lève ERR_INVALID_URL
try {
  const url = new URL('not-a-url');
} catch (err) {
  console.log(err.code);    // 'ERR_INVALID_URL'
  console.log(err.message); // 'Invalid URL: not-a-url'
  console.log(err.input);   // 'not-a-url'
}

Causes fréquentes et solutions

Cause 1 : protocole/schéma manquant. Le constructeur URL exige un schéma comme https:// ou http://. Des chaînes telles que example.com/path ou www.example.com échoueront.

// ÉCHEC : pas de protocole
new URL('example.com/path');  // ERR_INVALID_URL

// CORRECTION : ajouter le protocole
new URL('https://example.com/path');  // Fonctionne !

// CORRECTION : ajouter le protocole s'il manque
function ensureProtocol(urlString) {
  if (!/^https?:\/\//i.test(urlString)) {
    return 'https://' + urlString;
  }
  return urlString;
}
new URL(ensureProtocol('example.com/path'));  // Fonctionne !

Cause 2 : caractères spéciaux non encodés. Les caractères tels que les espaces, les accolades, les barres verticales et certains caractères Unicode ne sont pas autorisés dans les URL sans encodage.

// ÉCHEC : espaces et caractères spéciaux non encodés
new URL('https://example.com/my file.pdf');    // ERR_INVALID_URL
new URL('https://example.com/path?q=a b');     // Peut échouer dans certaines versions

// CORRECTION : encoder les parties problématiques
const filename = encodeURIComponent('my file.pdf');
new URL('https://example.com/' + filename);    // Fonctionne !

// CORRECTION : utiliser encodeURI pour une URL complète avec des espaces
const rawUrl = 'https://example.com/my file.pdf';
new URL(encodeURI(rawUrl));  // Fonctionne !

Cause 3 : encodage pour cent incorrect. Si une URL contient un signe pour cent qui n'est pas suivi d'exactement deux chiffres hexadécimaux, l'analyseur la rejette.

// ÉCHEC : encodage pour cent incorrect
new URL('https://example.com/100%done');       // ERR_INVALID_URL
new URL('https://example.com/path?q=50%');     // ERR_INVALID_URL

// CORRECTION : encoder le signe pour cent isolé en %25
function fixPercentSigns(urlString) {
  return urlString.replace(/%(?![0-9A-Fa-f]{2})/g, '%25');
}
new URL(fixPercentSigns('https://example.com/100%done'));
// Fonctionne ! L'URL devient https://example.com/100%25done

Cause 4 : entrée vide ou nulle. Passer une chaîne vide, null ou undefined au constructeur URL déclenche également cette erreur.

// ÉCHEC : entrée vide ou nulle
new URL('');           // ERR_INVALID_URL
new URL(null);         // ERR_INVALID_URL
new URL(undefined);    // ERR_INVALID_URL

// CORRECTION : valider l'entrée avant l'analyse
function parseUrl(input) {
  if (!input || typeof input !== 'string') {
    return null;
  }
  try {
    return new URL(input);
  } catch {
    return null;
  }
}

Cause 5 : URL relatives sans base. Le constructeur URL traite le premier argument comme une URL absolue par défaut. Les URL relatives comme /path/to/page nécessitent une URL de base comme second argument.

// ÉCHEC : URL relative sans base
new URL('/api/users');  // ERR_INVALID_URL

// CORRECTION : fournir une URL de base
new URL('/api/users', 'https://example.com');
// Fonctionne ! → https://example.com/api/users

// Modèle utile pour les clients d'API
const BASE_URL = 'https://api.example.com';
const endpoint = new URL('/v2/users?page=1', BASE_URL);
console.log(endpoint.href);
// "https://api.example.com/v2/users?page=1"

Comment valider les URL avant l'analyse

La méthode la plus fiable pour valider une URL dans Node.js consiste à utiliser le constructeur URL dans un bloc try-catch. Il n'existe pas de méthode intégrée URL.isValid() (au moment de Node.js 22), donc capturer l'erreur est l'approche standard.

// Validateur d'URL simple
function isValidUrl(string) {
  try {
    new URL(string);
    return true;
  } catch {
    return false;
  }
}

console.log(isValidUrl('https://example.com'));  // true
console.log(isValidUrl('not-a-url'));            // false
console.log(isValidUrl(''));                     // false

// Validateur avec protocoles autorisés
function isValidHttpUrl(string) {
  try {
    const url = new URL(string);
    return url.protocol === 'http:' || url.protocol === 'https:';
  } catch {
    return false;
  }
}

console.log(isValidHttpUrl('https://example.com'));     // true
console.log(isValidHttpUrl('ftp://example.com'));       // false
console.log(isValidHttpUrl('javascript:alert(1)'));     // false

Modèle d'analyse d'URL sécurisé

Voici un modèle d'analyse d'URL robuste qui gère tous les cas d'erreur courants et renvoie un objet URL analysé ou une erreur explicite.

class UrlParser {
  static parse(input, base) {
    // Valider l'entrée
    if (!input || typeof input !== 'string') {
      return { ok: false, error: 'Input must be a non-empty string' };
    }

    // Supprimer les espaces
    const trimmed = input.trim();

    // Corriger les problèmes courants
    let urlString = trimmed;

    // Ajouter le protocole s'il manque
    if (/^[a-zA-Z0-9]/.test(urlString) && !urlString.includes('://')) {
      urlString = 'https://' + urlString;
    }

    // Corriger les signes pour cent isolés
    urlString = urlString.replace(/%(?![0-9A-Fa-f]{2})/g, '%25');

    try {
      const url = base ? new URL(urlString, base) : new URL(urlString);

      // Facultatif : restreindre aux protocoles sûrs
      if (!['http:', 'https:'].includes(url.protocol)) {
        return { ok: false, error: 'Unsupported protocol: ' + url.protocol };
      }

      return { ok: true, url };
    } catch (err) {
      return { ok: false, error: err.message };
    }
  }
}

// Utilisation
const result = UrlParser.parse('example.com/path?q=hello world');
if (result.ok) {
  console.log(result.url.href);
} else {
  console.error(result.error);
}

Bonnes pratiques de prévention

Suivre ces pratiques vous aidera à éviter les erreurs ERR_INVALID_URL dans vos applications Node.js et à construire une gestion des URL plus résiliente.

  • Encadrez toujours l'analyse des URL avec try-catch. Ne supposez jamais qu'une chaîne d'URL est valide, surtout lorsqu'elle provient d'une entrée utilisateur, de variables d'environnement, de bases de données ou d'API externes.
  • Utilisez l'API URL plutôt que la concaténation de chaînes. Construisez les URL avec le constructeur URL et URLSearchParams au lieu de concaténer des chaînes. L'API gère l'encodage automatiquement.
  • Validez les variables d'environnement au démarrage. Si votre application lit des URL dans des variables d'environnement ou des fichiers de configuration, validez-les au démarrage de l'application, et non lors de leur première utilisation.
  • Encodez l'entrée utilisateur avant de l'intégrer dans des URL. Utilisez toujours encodeURIComponent() pour les valeurs des paramètres de requête et encodeURI() pour les URL complètes fournies par les utilisateurs.
  • Utilisez un générateur d'URL pour les cas complexes. Pour construire des URL comportant de nombreuses parties dynamiques, créez une fonction utilitaire ou une classe qui gère l'encodage de manière cohérente.
  • Journalisez l'entrée d'origine en cas d'erreur. Lorsque vous capturez une erreur ERR_INVALID_URL, journalisez l'entrée qui l'a provoquée (assainie si elle peut contenir des données sensibles) pour faciliter le débogage.
// Bonne pratique : valider les URL de configuration au démarrage
const requiredUrls = ['API_BASE_URL', 'AUTH_SERVER_URL', 'WEBHOOK_URL'];

for (const envVar of requiredUrls) {
  const value = process.env[envVar];
  if (!value) {
    throw new Error(envVar + ' environment variable is required');
  }
  try {
    new URL(value);
  } catch {
    throw new Error(envVar + ' is not a valid URL: ' + value);
  }
}

// Bonne pratique : utiliser l'API URL pour construire les URL
function buildApiUrl(endpoint, params) {
  const url = new URL(endpoint, process.env.API_BASE_URL);
  for (const [key, value] of Object.entries(params)) {
    url.searchParams.set(key, String(value));
  }
  return url.toString();
}

const searchUrl = buildApiUrl('/api/search', {
  q: 'Node.js & Express',
  page: 1
});
// "https://api.example.com/api/search?q=Node.js+%26+Express&page=1"

Articles connexes

Essayez nos outils gratuits