Immediate Fix
The fastest way to fix URIError: malformed URI sequence is to wrap your decoding logic in a try...catch block. This prevents the application from crashing when it encounters invalid percent-encoded characters.
// Standard safe decoding pattern
function safeDecode(uri) {
try {
return decodeURIComponent(uri);
} catch (e) {
console.error("Decoding failed:", e);
return uri; // Return the original string if malformed
}
}
const result = safeDecode("https://example.com/search?q=%E0%A4%A");
// Returns original string instead of throwing error
Alternatively, you can sanitize the string by replacing lone percent signs that aren’t followed by two hexadecimal digits. This is useful when dealing with user-generated content that contains literal “%” symbols.
function sanitizeAndDecode(uri) {
const sanitized = uri.replace(/%(?![0-9a-fA-F]{2})/g, "%25");
return decodeURIComponent(sanitized);
}
Technical Explanation
This error occurs when the JavaScript functions decodeURI() or decodeURIComponent() encounter a percent sign (%) that is not followed by a valid sequence of hexadecimal digits. It also triggers when a multi-byte UTF-8 character is truncated or incomplete.
According to the URI standard, a percent sign must be followed by two characters from 0-9 or A-F. If you have a URL like /path/%z1 or a trailing % at the end of the string, the JavaScript engine cannot map that sequence to a valid character, resulting in a URIError.

Common causes include copying partial URLs, handling raw data that uses “%” as a literal character without encoding it as %25, or incorrect character encoding transformations during data transit.
Alternative Methods
Method 1: Manual Character Replacement
If you know your input specifically contains lone percent signs (like “Sale: 50% Off”), use a global replace before decoding. This ensures the decoder treats the percent sign as literal data.
const input = "discount_10%";
const fixed = decodeURIComponent(input.replace(/%/g, '%25'));
Method 2: Validation Table
Before processing large batches of URLs, use this comparison table to decide which function to use based on your specific requirements:
| Function | Best Use Case | Throws URIError? |
|---|---|---|
| decodeURI() | Full URLs with protocols | Yes |
| decodeURIComponent() | Query parameters and fragments | Yes |
| unescape() (Deprecated) | Legacy support (Not recommended) | No |
Method 3: Encoding First
The best long-term fix is ensuring data is encoded correctly at the source. Use encodeURIComponent() whenever you append variables to a URL string. This prevents the “malformed” state from ever occurring by properly escaping reserved characters.
const query = "Coffee & Cream % 100";
const safeURL = `https://api.com/search?q=${encodeURIComponent(query)}`;
// Result: ...?q=Coffee%20%26%20Cream%20%25%20100