デバッグ7 分で読めます

JavaScript で発生する「URI Malformed」エラーの解決方法

JavaScript でよく発生する「URIError: URI malformed」エラーの原因を突き止め、実践的な解決策で修正する方法を解説します。

URIError: URI Malformed エラーを理解する

URIError: URI malformed エラーは、不正な percent-encoding のシーケンスを含む文字列をデコードしようとしたときに JavaScript で発生します。このエラーは、decodeURI()decodeURIComponent() が不正な形式のエンコード文字に遭遇した際にスローされます。

よくある原因

1. 単独のパーセント記号

直後に 16 進数 2 桁が続かないパーセント記号(%)は不正です。たとえば、%%G%2(不完全)などはいずれもこのエラーを引き起こします。

// これらは URIError をスローします
decodeURIComponent('%');        // 単独の %
decodeURIComponent('%2');       // 不完全なシーケンス
decodeURIComponent('%GH');      // 不正な 16 進数
decodeURIComponent('100%');     // 末尾に 16 進数のない %

2. 不正な UTF-8 シーケンス

percent-encoding されたバイト列が有効な UTF-8 文字シーケンスを構成しない場合、デコーダはそれを文字列に変換できません。これは、データが破損している場合や、異なる文字エンコーディングでエンコードされていた場合に発生することがあります。

3. 二重エンコード

二重エンコードは、すでにエンコード済みの文字列をさらにエンコードしたときに発生します。たとえば、%20(エンコードされたスペース)は %2520 にエンコードされます。元の文字列をデコードしようとすると、シーケンスが不正になることがあります。

解決方法

解決策 1: try-catch を使う

function safeDecode(str) {
  try {
    return decodeURIComponent(str);
  } catch (e) {
    // デコードに失敗した場合は元の文字列を返す
    console.warn('Failed to decode:', str, e.message);
    return str;
  }
}

解決策 2: デコード前に検証する

function isValidEncodedURI(str) {
  try {
    decodeURIComponent(str);
    return true;
  } catch {
    return false;
  }
}

function fixMalformedURI(str) {
  // 単独の % を %25(エンコードされたパーセント記号)に置換する
  return str.replace(/%(?![0-9A-Fa-f]{2})/g, '%25');
}

解決策 3: 二重エンコードを防ぐ

function smartEncode(str) {
  // まずデコードを試みる。成功すれば、その文字列は
  // すでにエンコード済みである
  try {
    const decoded = decodeURIComponent(str);
    // デコードで文字列が変化した場合、それはエンコードされていた
    if (decoded !== str) {
      return str; // すでにエンコード済みなのでそのまま返す
    }
  } catch {
    // 有効なエンコード文字列ではないのでエンコードする
  }
  return encodeURIComponent(str);
}

予防のためのベストプラクティス

  • ユーザー入力や外部から取得した URL をデコードする際は、必ず try-catch を使う
  • 処理する前に URL を検証する
  • 値を二重エンコードしないよう注意する
  • 可能な場合は URL および URLSearchParams API を使う。これらはエンコードを正しく処理してくれる
  • エンコードする前にクエリ文字列の値をサニタイズする
  • デバッグのために不正な URL をログに記録する

関連記事

無料ツールを試す