"URIError: URI malformed" および一般的な URL エラーの解決方法:完全ガイド
URL (Uniform Resource Locator) はウェブの住所です。一見シンプルに見えますが、使用できる文字には厳格なルールがあります。これらのルールが守られないと、URIError: URI malformed や TypeError: 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 (不完全)
解決策:
- 単独の % 記号をエスケープする: 文字列にエンコードシーケンスの一部ではないリテラルの
%記号が含まれている場合は、%25としてエスケープする必要があります。 - データの欠落を確認する: データベースのフィールド制限や長いクエリパラメータなどで、URL がシーケンスの途中で切り捨てられていないか確認してください。
- 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 を使用しています。GBK や Latin1 を使用している古いシステムの URL パラメータに遭遇すると、decodeURIComponent は失敗するか、文字化け(mojibake)を引き起こします。
解決策: URL を処理する前に、iconv-lite などのライブラリを使用してレガシーエンコーディングを適切に処理する必要があるかもしれません。
4. 予防策とベストプラクティス
URLAPI を使用する: 手動で文字列を連結する代わりに、組み込みのURLおよびURLSearchParamsAPI を使用してください。これらはエンコードを自動的かつ正しく処理します。- 用途を明確にする: パラメータ値には
encodeURIComponentを、ベースパスにはencodeURIを使用します。 - 入力をサニタイズする: ユーザーが提供した 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 が正しく形成されているかを即座に 検証。
encodeURIとencodeURIComponentの結果を 比較。- 複雑なクエリ文字列を安全に デコード。
- 国際化ドメイン名 (IDN) への対応。
関連するエラー
- JSON の 'Unexpected token' エラーの解決方法
- 'invalid base64 string' エラーの修正方法
- URIError: URI malformed を理解する