! LaTeX Error: Option clash for package inputenc suele explicarse como «el mismo paquete se cargó dos veces con opciones distintas», y no es del todo cierto. Lo que latex.ltx hace en realidad es una prueba de subconjunto: el segundo \usepackage pasa si todas las opciones que pide ya estaban entre las de la primera carga, y choca en cuanto aparece un nombre nuevo. Por eso \usepackage[a,b]{X} seguido de \usepackage[a]{X} va bien mientras que el orden inverso falla. Más incómodo aún: algunos paquetes se saltan la prueba por completo, y xcolor es el ejemplo estrella. Esta página cubre cuál es la regla de verdad, dónde ha de ir exactamente \PassOptionsToPackage, por qué hyperref se carga casi al final y qué parejas de paquetes siguen negándose de veras a convivir en TeX Live 2024.
El choque lo desencadena una opción nueva, no una opción distinta
Un segundo \usepackage choca en el instante en que pide una opción que la primera carga no tenía. Si en cambio pide un subconjunto de las opciones iniciales —en cualquier orden, en menor número o ninguna—, no ocurre nada. El motivo está en latex.ltx: \@onefilewithoptions@clashchk llama a \@if@ptions, cuyo \@if@pti@ns interno recorre las opciones pedidas una a una y busca cada una en la lista registrada con \in@. Basta un fallo para seleccionar la segunda rama, es decir \@latex@error{Option clash for …}. Se ejecutaron siete combinaciones en TeX Live 2024; la tabla siguiente es el resultado, y de ella se desprende la regla.
| primera carga, luego segunda | Resultado, medido en TeX Live 2024 |
|---|---|
[alpha] → [beta] | choque — beta es un nombre que la primera carga no tenía |
[alpha] → [alpha] | sin choque — repetir la misma opción no produce nada |
[alpha] → [] | sin choque — el conjunto vacío siempre es subconjunto, así que recargar sin opciones es seguro |
[] → [alpha] | choque — el caso clásico de que la clase u otro paquete se adelantara |
[alpha,beta] → [alpha] | sin choque — pedir menos siempre está permitido |
[alpha] → [alpha,beta] | choque — pedir más falla; la solución es dar todas las opciones en la primera carga |
[beta,alpha] → [alpha,beta] | sin choque — el orden es indiferente; la comparación es entre conjuntos |
La línea de error es escueta, pero el .log detalla con qué opciones se cargó el paquete la primera vez y cuáles se acaban de pedir. Esas cuatro líneas son todo el diagnóstico, así que conviene abrir el registro en lugar de forzar la vista en el terminal. Otra cosa que compensa saber: el número de línea informado está desplazado. Como \usepackage admite un argumento de fecha opcional al final, tiene que mirar más allá de la llave de cierre por si hay un [, y esa anticipación alcanza la línea siguiente. Por eso un choque causado por un \usepackage en la línea 3 se informa como l.4 \begin{document}.
% terminal shows only the first line; the rest is in the .log
./oc1.tex:4: LaTeX Error: Option clash for package inputenc.
l.4 \begin
{document}
The package inputenc has already been loaded with options:
[utf8]
There has now been an attempt to load it with options
[latin1]
Adding the global options:
utf8,latin1
to your \documentclass declaration may fix this.Por qué xcolor nunca choca: tres formas de esquivar la prueba
Escribir \usepackage[dvipsnames]{xcolor} y luego \usepackage[table]{xcolor} no produce error alguno en TeX Live 2024 — no porque xcolor sea especialmente indulgente, sino porque la prueba de subconjunto nunca llega a invocarse. Para un paquete ya cargado, \@onefilewithoptions de latex.ltx comprueba primero si existe una macro llamada opt@handler@<paquete>.sty. Si no existe, el control pasa a \@onefilewithoptions@clashchk, la prueba de subconjunto de antes. Si existe, el núcleo cede el asunto por completo y deja que ese manejador procese las opciones recién pedidas. Y xcolor.sty en TeX Live 2024 ya ha migrado al esquema moderno: declara sus opciones con \DeclareKeys y las procesa con \ProcessKeyOptions, y es precisamente \ProcessKeyOptions quien registra opt@[email protected]. Un \show devuelve un cuerpo de una sola línea: \ProcessKeyOptions [xcolor].
% no error on TeX Live 2024: xcolor uses \DeclareKeys + \ProcessKeyOptions
\usepackage[dvipsnames]{xcolor}
\usepackage[table]{xcolor}
% still an error: inputenc uses the classic \DeclareOption mechanism
\usepackage[utf8]{inputenc}
\usepackage[latin1]{inputenc}
% check for yourself which mechanism a package uses
\makeatletter
\expandafter\show\csname opt@[email protected]\endcsname
% -> \opt@[email protected]=\protected\long macro: ->\ProcessKeyOptions [xcolor].
\makeatotherPasar a opciones clave-valor es el rodeo más educado, pero hay otros dos. fontenc.sty cierra su propio archivo devolviendo a \relax tanto [email protected] como [email protected] — y como \@ifl@aded decide mirando ver@…, fontenc borra el hecho mismo de haber sido cargado, de modo que el siguiente \usepackage[T2A]{fontenc} cuenta como primera carga. El otro caso es caption, que dentro de caption3.sty sustituye lisa y llanamente el \@onefilewithoptions del núcleo: cuando un paquete de la familia caption se vuelve a cargar, las opciones nuevas se encaminan al equivalente de \captionsetup y después el paquete se recarga con una lista de opciones vacía. El comentario del autor justo encima de ese código cuenta que pidió al equipo de LaTeX una interfaz en condiciones en 2018 y de nuevo en 2020 y se la denegaron, y él mismo llama a su sustitución un «dirty hack». Detrás de un paquete que se niega a chocar en silencio suele estar una de estas tres técnicas.
| Paquete, recargado con una opción nueva | Resultado en TeX Live 2024 y por qué |
|---|---|
xcolor | sin choque: usa \DeclareKeys y \ProcessKeyOptions, así que la prueba se evita |
fontenc | sin choque: borra [email protected] al final de su carga y vuelve a parecer no cargado |
caption | sin choque: caption3.sty sustituye el \@onefilewithoptions del núcleo |
inputenc | choca: sigue usando el mecanismo clásico \DeclareOption |
geometry | choca: para añadir ajustes use \geometry{…} en lugar de cargarlo otra vez |
hyperref | choca: para añadir ajustes use \hypersetup{…} en lugar de cargarlo otra vez |
babel | choca: enumere todos los idiomas en un solo \usepackage en lugar de cargarlo dos veces |
amsmath | choca: opciones como fleqn y leqno se dan por convención a la clase |
Dónde va \PassOptionsToPackage: antes de la primera carga, y en ningún otro sitio
\PassOptionsToPackage{opt}{X} solo significa algo si va antes de la primera carga de X, y el sitio fiable es la primera línea del archivo, por encima de \documentclass. Lo único que hace el comando es añadir opt a la lista de opciones [email protected] — y ese único gesto compra los dos efectos a la vez: opt se entrega a X en el momento de cargarse, y cualquier \usepackage[opt]{X} posterior pasa ya la prueba de subconjunto. Hacer efectiva la opción y hacer desaparecer el choque no son dos arreglos distintos: son las dos caras de la misma línea. Puede ir sobre \documentclass porque \PassOptionsToPackage está definido a nivel de formato y, a diferencia de \usepackage, no presupone que se haya leído una clase.
% correct: the very first line, above \documentclass
\PassOptionsToPackage{table}{xcolor}
\documentclass{article}
\usepackage{tikz} % pulls xcolor in -- with table already attached
\usepackage[table]{xcolor} % no clash, and \rowcolor works
% WRONG: after xcolor is already loaded. No error is raised, and the
% option is silently never executed.
\documentclass{article}
\usepackage{tikz}
\PassOptionsToPackage{table}{xcolor}
\usepackage[table]{xcolor}El comando tiene una manera muy silenciosa de fallar. Colocar \PassOptionsToPackage después de que X ya se haya cargado no provoca error alguno, pero la opción no llega a ejecutarse nunca. Medido con un paquete de prueba instrumentado: colocada antes de la carga, el código de la opción se ejecuta de forma comprobable; colocada después, el choque desaparece y el código sigue sin ejecutarse. Creer que el problema está resuelto porque el error se fue es la forma más peligrosa de usar esta herramienta. Hay una segunda trampa en el propio texto del error, que sugiere añadir las opciones globalmente a \documentclass. Al pie de la letra no funciona: añadir \documentclass[beta]{article} conservando \usepackage[alpha]{X} y \usepackage[beta]{X} reproduce el choque igual que antes. Solo quitando ambas listas locales de opciones —\documentclass[alpha,beta]{article} con dos \usepackage{X} pelados— se consigue pasar.
Averiguar qué cargó el paquete que nunca pidió
Basta una línea \listfiles en el preámbulo para que el final del .log liste todos los archivos realmente cargados; y quién arrastró cada uno lo responde el anidamiento de paréntesis del registro. Un ( abre un archivo y ) lo cierra, así que si el ( que abre xcolor.sty queda dentro de los paréntesis de pgfcore.sty, quien lo arrastró es pgf. Medido: un article pelado lee 3 archivos, una línea de tikz lo lleva a 34, y xcolor está entre ellos; hyperref por sí solo aporta 30. «Nunca escribí xcolor y me sale un option clash» casi siempre encuentra su respuesta en esa lista. Para un rastro más fino, -recorder escribe cada archivo abierto en un .fls.
% the nesting says who pulled xcolor in: pgf did
(.../pgf/basiclayer/pgfcore.sty
(.../pgf/systemlayer/pgfsys.sty
...
)) (.../xcolor/xcolor.sty
...
)
% and with \listfiles, the summary table at the end of the .log
*File List*
article.cls 2023/05/17 v1.4n Standard LaTeX document class
xcolor.sty 2022/06/12 v2.14 LaTeX color extensions (UK)
***********Orden de carga: por qué hyperref va casi al final y qué va después
hyperref se carga casi al final porque sobrescribe una gran cantidad de mecanismos —\ref, \cite, \caption, el índice general, el índice alfabético— y una sobrescritura debe aplicarse sobre la definición final. Si algo posterior redefine lo mismo, el trabajo de hyperref queda sencillamente borrado. Pero la regla dice «casi al final», no «el último». Los paquetes construidos sobre lo que hace hyperref deben ir, naturalmente, después: bookmark, cleveref, hypcap y glossaries son los habituales. cleveref en particular detecta él mismo la infracción y lanza un error, así que equivocarse se ve al instante; sus requisitos exactos los trata la página de referencias indefinidas.
Conviene decir una cosa con claridad. Buena parte del folclore del tipo «A debe ir antes que B» no produce efecto alguno en TeX Live 2024. Probar float con hyperref, geometry con hyperref, algorithm con hyperref, bookmark con hyperref y glossaries con hyperref en ambos órdenes no dio, en ningún caso, ni error ni advertencia; los paquetes llevan años acumulando código de compatibilidad. Así que las reglas de orden que merece la pena obedecer son las que enuncia el manual del propio paquete, y reordenar un preámbulo para satisfacer una afirmación de origen desconocido suele ser tiempo perdido. La costumbre de poner hyperref casi al final sigue mereciendo la pena, porque se desprende de la naturaleza misma de la sobrescritura y no de un rumor.
La diferencia entre \usepackage y \RequirePackage
Dentro del preámbulo los dos son literalmente lo mismo: al procesar \documentclass, latex.ltx ejecuta \let\usepackage\RequirePackage, de modo que a partir de ahí son un único comando. La diferencia solo existe antes de \documentclass y dentro de los archivos .sty y .cls. En esos lugares, \usepackage se detiene con ! LaTeX Error: \usepackage before \documentclass. — el \usepackage de nivel de formato está definido únicamente para emitir ese diagnóstico. Por eso un paquete o una clase propios usan \RequirePackage, y por eso la combinación con \PassOptionsToPackage permite inyectar una opción por encima de \documentclass. Cuando una clase quiere pasar sus propias opciones tal cual a un paquete que carga, existe \RequirePackageWithOptions justo para eso.
% before \documentclass, only \RequirePackage works
\RequirePackage{fix-cm}
\PassOptionsToPackage{table}{xcolor}
\documentclass{article}
% inside your own mystyle.sty, likewise
\ProvidesPackage{mystyle}[2026/01/01 house style]
\RequirePackage{xcolor}
\RequirePackageWithOptions{geometry} % forward this package's own optionsParejas que de verdad se niegan a convivir, comprobadas en TeX Live 2024
Más allá de las opciones, algunas parejas no pueden convivir porque definen dos veces la misma maquinaria. Son menos de las que sugiere el folclore, y el síntoma no siempre es un error al cargar. La que se niega sin rodeos es biblatex con natbib: la compilación se detiene en ! Package biblatex Error: Incompatible package 'natbib'. — y si solo se quería \citet y \citep, \usepackage[natbib=true]{biblatex} los da. El caso incómodo es el que se rompe en silencio: cargar a la vez subfigure y subcaption no provoca ningún error. El problema aflora mucho después, como ! Missing number, treated as zero. en la línea donde se escribió \begin{subfigure}{0.4\textwidth}, porque \begin{subfigure} lo absorbe el viejo comando \subfigure que define subfigure y se lee de un modo completamente distinto.
| Pareja | Qué ocurre realmente en TeX Live 2024 |
|---|---|
biblatex + natbib | se detiene de inmediato con un error; unifique en \usepackage[natbib=true]{biblatex} |
natbib + biblatex | en este orden no hay error, solo advertencias de que se redefinen \citeauthor y afines |
subfigure + subcaption | ambos cargan sin rechistar; más tarde \begin{subfigure} se rompe y da errores de aspecto ajeno |
subfig + subcaption | ambos cargan, pero subcaption renuncia a definir su entorno, y sale ! LaTeX Error: Environment subfigure undefined. |
caption + subfigure | ya no hay choque; el .log solo anota Package caption Info: subfigure package is loaded. |
cleveref + hyperref | cargar cleveref primero detiene la compilación; ha de ir después de hyperref y de varioref |
cite + natbib | sin error, pero natbib advierte de que no debería usarse cite junto a él; conserve solo uno |
La lección que hay que sacar de esa tabla es dejar de creer de oídas que «A y B son incompatibles» y construir un documento de cinco líneas para comprobarlo. La incompatibilidad de caption con subfigure fue realmente un error en su día; hoy está degradada a un Info. En sentido inverso, subfigure con subcaption es el caso más claro en que «cargó sin error, así que todo bien» es la conclusión peligrosa. El síntoma se ha desplazado del error al cargar a un error mucho posterior y de apariencia ajena: ahí está la incompatibilidad de paquetes en TeX Live 2024, y por eso justamente compensa el hábito de poner \listfiles y leer el .log.