Guía

Cómo corregir URIError: URI malformed en JavaScript

Localiza escapes porcentuales incompletos, bytes UTF-8 inválidos y sustitutos Unicode aislados que causan URI malformed.

por Tools in a Tab · Publicado el · Revisado el

Respuesta breve

URIError: URI malformed suele significar una de dos cosas: al decodificar, hay un % incompleto o una secuencia de bytes que no es UTF-8; al codificar, la cadena JavaScript contiene un sustituto Unicode aislado. No tapes el error con un try/catch vacío: conserva la entrada, identifica la operación y corrige la capa que produjo el valor.

Primero distingue codificación y decodificación

decodeURIComponent y decodeURI leen secuencias %HH. Fallan si encuentran %, %A, %GG o bytes que no forman un carácter UTF-8 válido. Por ejemplo, %E0%A4%A está truncado y no puede terminar la secuencia iniciada.

encodeURIComponent y encodeURI trabajan con texto Unicode. Pueden fallar si la cadena contiene una mitad de par sustituto, algo posible al cortar una cadena UTF-16 por índice o recibir datos internos corruptos.

El codificador y decodificador URL separa los modos componente, URL completa y valor de formulario, y devuelve diagnósticos sin enviar la entrada.

Escapes porcentuales incompletos

Cada % debe ir seguido exactamente por dos dígitos hexadecimales. %20 es un espacio y %2F representa /; %2, %XZ y un % final no son escapes válidos. Revisa la cadena original antes de sustituir % por %25, porque esa operación puede convertir un dato roto en el texto literal de un escape roto.

Un error frecuente aparece al interpolar un porcentaje humano, como 50%, en una URL y luego decodificarla. Si es parte de un valor, debe codificarse como 50%25 en el límite donde se construye ese componente.

Secuencias UTF-8 inválidas

Una serie de escapes puede tener pares hexadecimales correctos y seguir siendo inválida. decodeURIComponent('%C3%28') falla porque C3 inicia una secuencia UTF-8 de dos bytes, pero 28 no es un byte de continuación. No decodifiques cada %HH directamente como un carácter Latin-1: reúne los bytes y aplica UTF-8 de forma estricta.

MDN documenta ambos casos en la referencia de URI malformed error. La solución correcta suele estar en el productor que truncó o codificó con otra tabla de caracteres.

Sustitutos Unicode aislados al codificar

JavaScript almacena cadenas como unidades UTF-16. Muchos caracteres fuera del plano básico, incluidos emojis, usan dos unidades llamadas par sustituto. Si cortas justo entre ambas, queda un sustituto alto o bajo aislado que no representa ningún valor Unicode válido; encodeURI puede lanzar URIError.

Evita truncar texto con slice() por unidades cuando debas respetar caracteres. Iterar con Array.from(text) o for…of trabaja por puntos de código, aunque secuencias visuales complejas pueden requerir segmentación de grafemas. También puedes comprobar text.isWellFormed() cuando el entorno lo soporte.

Método de depuración

  1. Registra de forma segura si el fallo ocurre al codificar o decodificar, sin exponer datos sensibles.
  2. Para decodificación, busca el primer % que no tenga dos hexadecimales.
  3. Si la sintaxis es correcta, convierte todos los escapes a bytes y valida UTF-8.
  4. Para codificación, comprueba que la cadena Unicode esté bien formada.
  5. Confirma si la función debía actuar sobre un componente o la URL completa.

No apliques varias veces decodeURIComponent hasta que deje de cambiar. Cada capa necesita una justificación contractual y una segunda pasada puede convertir datos codificados en separadores activos.

Prevención

Mantén valores sin codificar dentro de la aplicación y codifícalos una sola vez al insertarlos. Usa URL y URLSearchParams para construir direcciones, valida entradas externas antes de decodificarlas y guarda pruebas con tildes, emoji, %, secuencias truncadas y bytes inválidos. Un error visible es más seguro que continuar con una URL cuyo significado haya cambiado.