url debugging web-development javascript encoding

'URIError: URI malformed' および一般的な URL エラーの解決方法

'URIError: URI malformed'、'invalid URL'、パーセントエンコーディングの問題など、URL エラーの修正に関する包括的なガイド。encodeURI と encodeURIComponent の違いを学びましょう。

"URIError: URI malformed" および一般的な URL エラーの解決方法:完全ガイド

URL (Uniform Resource Locator) はウェブの住所です。一見シンプルに見えますが、使用できる文字には厳格なルールがあります。これらのルールが守られないと、URIError: URI malformedTypeError: Failed to construct 'URL': Invalid URL、あるいは単に 404 エラーにつながる壊れたリンクなどのエラーが発生します。

このガイドでは、最も一般的な URL 関連のエラーとその解決方法を、JavaScript やその他の環境について詳しく解説します。


1. 一般的な URL エラーメッセージ

操作の内容に応じて、以下のようなエラーに遭遇することがあります:

  • JavaScript (decodeURIComponent): URIError: URI malformed
  • JavaScript (new URL()): TypeError: Failed to construct 'URL': Invalid URL
  • Python (urllib): ValueError: Invalid URL
  • Java (URLDecoder): java.lang.IllegalArgumentException: URLDecoder: Incomplete % sequence

2. 主な原因と解決策

2.1 "URIError: URI malformed"

このエラーは、JavaScript の decodeURI()decodeURIComponent() が無効な パーセントエンコーディング (percent encoding error) シーケンスに遭遇したときに発生します。通常、% 記号の後に 2 桁の 16 進数が続いていないか、シーケンスが無効な UTF-8 文字を表している場合に起こります。

エラーの例:

decodeURIComponent("%") // URIError: URI malformed
decodeURIComponent("%E0%A4%A") // URIError: URI malformed (不完全)

解決策:

  1. 単独の % 記号をエスケープする: 文字列にエンコードシーケンスの一部ではないリテラルの % 記号が含まれている場合は、%25 としてエスケープする必要があります。
  2. データの欠落を確認する: データベースのフィールド制限や長いクエリパラメータなどで、URL がシーケンスの途中で切り捨てられていないか確認してください。
  3. Try-Catch を使用する: デコード処理は常に try-catch ブロックで囲むようにしましょう。
function safeDecode(str) {
  try {
    return decodeURIComponent(str);
  } catch (e) {
    console.error("Malformed URL (不正な形式の URL):", str);
    return str; // デコードに失敗した場合は元の文字列を返す
  }
}

2.2 encodeURI と encodeURIComponent の使い分け

よくある間違いは、不適切なエンコード関数を使用してしまい、サーバーがリクエストを受け取ったときに invalid URL エラーが発生することです。

  • encodeURI(): URL 全体に対して使用します。URL 構造において特別な意味を持つ文字(:, /, ?, #, &, = など)はエンコードしません。
  • encodeURIComponent(): 個々のパラメータ(検索クエリやファイル名など)に対して使用します。一部の基本文字を除き、すべての文字をエンコードします。

間違った方法:

const url = "https://example.com/search?q=" + encodeURI("blue/green");
// 結果: https://example.com/search?q=blue/green (/ がパラメータを壊してしまいます)

正しい方法:

const url = "https://example.com/search?q=" + encodeURIComponent("blue/green");
// 結果: https://example.com/search?q=blue%2Fgreen (正しい!)

2.3 "TypeError: Invalid URL"

このエラーは、URL コンストラクタに有効な絶対 URL ではない文字列(https:// などのプロトコルが欠落している場合など)を渡したときに発生します。

エラーの例:

new URL("www.google.com") // TypeError: Invalid URL

解決策: URL が絶対パスであることを確認するか、第 2 引数としてベース URL を指定してください。

new URL("https://www.google.com") // 正解
new URL("/path", "https://example.com") // 正解

2.4 パーセントエンコーディングエラー (スペースと特殊文字)

URL にスペースを含めることはできません。一部のブラウザは自動的にスペースを %20+ に変換しますが、この動作に依存するのは危険です。

解決策: 動的なデータは常にエンコードしてください。

  • スペース -> %20 (標準)
  • スペース -> + (クエリ文字列内のみ有効、例: ?q=hello+world)

3. 高度なトラブルシューティング

3.1 二重エンコード (Double Encoding)

文字列を 2 回エンコードすると、データが混乱します。例えば、スペースが %20 になり、それがさらに %2520 になります。 解決策: どこでエンコードが行われているかを追跡してください。エンコードは、URL にデータを追加する直前の 1 回だけに留めます。

3.2 UTF-8 以外のエンコーディング

現代のウェブは UTF-8 を使用しています。GBKLatin1 を使用している古いシステムの URL パラメータに遭遇すると、decodeURIComponent は失敗するか、文字化け(mojibake)を引き起こします。 解決策: URL を処理する前に、iconv-lite などのライブラリを使用してレガシーエンコーディングを適切に処理する必要があるかもしれません。


4. 予防策とベストプラクティス

  1. URL API を使用する: 手動で文字列を連結する代わりに、組み込みの URL および URLSearchParams API を使用してください。これらはエンコードを自動的かつ正しく処理します。
  2. 用途を明確にする: パラメータ値には encodeURIComponent を、ベースパスには encodeURI を使用します。
  3. 入力をサニタイズする: ユーザーが提供した URL を扱う場合は、URL コンストラクタを try-catch ブロックで使用して検証してください。
function isValidUrl(string) {
  try {
    new URL(string);
    return true;
  } catch (_) {
    return false;  
  }
}

5. よくある質問 (FAQ)

Q: スペースのエンコードで %20 と + の違いは何ですか?

A: %20 は、URI のどの部分においてもスペース文字の標準的なエンコードです。+ は、主にクエリパラメータ (application/x-www-form-urlencoded) で使われる古い慣習です。互換性を最大にするには %20 を使用してください。

Q: URL に %25 が含まれているのはなぜですか?

A: %25% 文字自体がエンコードされたものです。これは通常、すでにエンコードされた URL が再度エンコードされた場合(二重エンコード)に発生します。

Q: 絵文字や非ラテン文字を含む URL はどう扱えばいいですか?

A: 常に encodeURIComponent を使用してください。Unicode 文字を適切に UTF-8 バイトシーケンスに変換し、各バイトをパーセントエンコードします。


6. クイックチェックツール

フォーマットが崩れた malformed URL でお困りですか?当サイトの URL エンコード・デコードツール をご利用ください。以下のことが可能です:

  • URL が正しく形成されているかを即座に 検証
  • encodeURIencodeURIComponent の結果を 比較
  • 複雑なクエリ文字列を安全に デコード
  • 国際化ドメイン名 (IDN) への対応。

関連するエラー

  • JSON の 'Unexpected token' エラーの解決方法
  • 'invalid base64 string' エラーの修正方法
  • URIError: URI malformed を理解する