! LaTeX Error: Option clash for package inputenc s'explique d'ordinaire par « le même package a été chargé deux fois avec des options différentes », ce qui n'est pas tout à fait exact. Ce que latex.ltx effectue réellement est un test d'inclusion : le second \usepackage passe si chacune des options demandées figurait déjà parmi celles du premier chargement, et entre en conflit dès qu'un nom nouveau apparaît. D'où le fait que \usepackage[a,b]{X} suivi de \usepackage[a]{X} ne pose aucun problème alors que l'ordre inverse échoue. Plus gênant encore, certains packages contournent totalement ce test, xcolor en étant l'exemple le plus connu. Cette page traite de la règle réelle, de l'endroit exact où doit figurer \PassOptionsToPackage, de la raison pour laquelle hyperref se charge près de la fin, et des paires de packages qui refusent encore vraiment de cohabiter sur TeX Live 2024.
Le conflit est déclenché par une option nouvelle, pas par une option différente
Un second \usepackage entre en conflit dès l'instant où il réclame une option absente du premier chargement. À l'inverse, s'il demande un sous-ensemble des options initiales — dans n'importe quel ordre, en moins grand nombre, voire aucune —, rien ne se passe. La raison est dans latex.ltx : \@onefilewithoptions@clashchk appelle \@if@ptions, dont le \@if@pti@ns interne parcourt les options demandées une à une et cherche chacune dans la liste enregistrée avec \in@. Un seul échec suffit à sélectionner la seconde branche, c'est-à-dire \@latex@error{Option clash for …}. Sept combinaisons ont été exécutées sur TeX Live 2024 ; le tableau ci-dessous en donne le résultat, d'où la règle découle directement.
| premier chargement, puis second | Résultat, mesuré sur TeX Live 2024 |
|---|---|
[alpha] → [beta] | conflit — beta est un nom absent du premier chargement |
[alpha] → [alpha] | aucun conflit — répéter la même option ne produit rien |
[alpha] → [] | aucun conflit — l'ensemble vide est toujours un sous-ensemble, un rechargement nu est donc sûr |
[] → [alpha] | conflit — le cas classique où la classe ou un autre package a chargé en premier |
[alpha,beta] → [alpha] | aucun conflit — demander moins est toujours permis |
[alpha] → [alpha,beta] | conflit — demander davantage échoue ; la solution est de tout indiquer au premier chargement |
[beta,alpha] → [alpha,beta] | aucun conflit — l'ordre est indifférent, la comparaison porte sur des ensembles |
La ligne d'erreur est laconique, mais le .log détaille avec quelles options le package a d'abord été chargé et lesquelles viennent d'être demandées. Ces quatre lignes constituent le diagnostic à elles seules : mieux vaut ouvrir le journal que scruter le terminal. Autre chose utile à savoir : le numéro de ligne signalé est décalé. Comme \usepackage accepte un argument de date optionnel à la fin, il doit regarder au-delà de l'accolade fermante pour voir s'il y a un [, et cette anticipation atteint la ligne suivante. C'est pourquoi un conflit provoqué par un \usepackage en ligne 3 est signalé comme 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.Pourquoi xcolor n'entre jamais en conflit : trois façons de contourner le test
Écrire \usepackage[dvipsnames]{xcolor} puis \usepackage[table]{xcolor} ne produit aucune erreur sur TeX Live 2024 — non parce que xcolor serait particulièrement indulgent, mais parce que le test d'inclusion n'est jamais appelé. Pour un package déjà chargé, \@onefilewithoptions dans latex.ltx vérifie d'abord l'existence d'une macro nommée opt@handler@<package>.sty. Si elle n'existe pas, on passe à \@onefilewithoptions@clashchk, le test d'inclusion ci-dessus. Si elle existe, le noyau délègue entièrement et laisse ce gestionnaire traiter les options nouvellement demandées. Or xcolor.sty sur TeX Live 2024 est passé au dispositif moderne : il déclare ses options avec \DeclareKeys et les traite avec \ProcessKeyOptions, et c'est précisément \ProcessKeyOptions qui enregistre opt@[email protected]. Un \show en révèle le corps, tenant sur une ligne : \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].
\makeatotherLe passage aux options clé-valeur est le contournement le plus civil, mais il en existe deux autres. fontenc.sty termine son propre fichier en remettant à \relax aussi bien [email protected] que [email protected] — et puisque \@ifl@aded se décide en consultant ver@…, fontenc efface le fait même d'avoir été chargé, si bien que le \usepackage[T2A]{fontenc} suivant compte pour un premier chargement. L'autre cas est caption, qui dans caption3.sty remplace purement et simplement le \@onefilewithoptions du noyau : lorsqu'un package de la famille caption est rechargé, les nouvelles options sont aiguillées vers l'équivalent de \captionsetup, puis le package est rechargé avec une liste d'options vide. Le commentaire de l'auteur juste au-dessus indique qu'il a demandé à l'équipe LaTeX une interface en bonne et due forme en 2018 puis en 2020, et qu'on la lui a refusée ; il qualifie lui-même son remplacement de « dirty hack ». Derrière un package qui refuse discrètement d'entrer en conflit se cache le plus souvent l'une de ces trois techniques.
| Package, rechargé avec une option nouvelle | Résultat sur TeX Live 2024, et pourquoi |
|---|---|
xcolor | aucun conflit : il emploie \DeclareKeys et \ProcessKeyOptions, le test est contourné |
fontenc | aucun conflit : il efface [email protected] à la fin de son chargement et paraît de nouveau non chargé |
caption | aucun conflit : caption3.sty remplace le \@onefilewithoptions du noyau |
inputenc | entre en conflit : il utilise encore le mécanisme classique \DeclareOption |
geometry | entre en conflit : pour ajouter des réglages, employer \geometry{…} plutôt qu'un second chargement |
hyperref | entre en conflit : pour ajouter des réglages, employer \hypersetup{…} plutôt qu'un second chargement |
babel | entre en conflit : énumérer toutes les langues dans un seul \usepackage plutôt que de charger deux fois |
amsmath | entre en conflit : des options comme fleqn et leqno se donnent d'ordinaire à la classe |
Où placer \PassOptionsToPackage : avant le premier chargement, et nulle part ailleurs
\PassOptionsToPackage{opt}{X} ne signifie quelque chose que s'il précède le premier chargement de X, et l'endroit fiable est la première ligne du fichier, au-dessus de \documentclass. Tout ce que fait cette commande, c'est ajouter opt à la liste d'options [email protected] — et ce seul geste procure les deux effets à la fois : opt est transmis à X au moment de son chargement, et tout \usepackage[opt]{X} ultérieur passe désormais le test d'inclusion. Rendre l'option effective et faire disparaître le conflit ne sont pas deux corrections distinctes : ce sont les deux faces d'une même ligne. Elle peut figurer avant \documentclass parce que \PassOptionsToPackage est défini au niveau du format et ne suppose pas, contrairement à \usepackage, qu'une classe ait été lue.
% 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}Cette commande possède une manière très silencieuse d'échouer. Placer \PassOptionsToPackage après le chargement effectif de X ne déclenche aucune erreur — mais l'option n'est jamais exécutée. Mesuré avec un package de test instrumenté : placée avant le chargement, le code de l'option s'exécute de façon vérifiable ; placée après, le conflit disparaît et le code reste inexécuté. Croire le problème résolu parce que l'erreur a disparu est la façon la plus dangereuse d'employer cet outil. Un second piège se cache dans le texte d'erreur lui-même, qui suggère d'ajouter les options globalement à \documentclass. Suivi à la lettre, cela ne marche pas : ajouter \documentclass[beta]{article} tout en conservant \usepackage[alpha]{X} et \usepackage[beta]{X} reproduit le conflit à l'identique. Il faut supprimer les deux listes d'options locales — \documentclass[alpha,beta]{article} et deux \usepackage{X} nus — pour que cela passe.
Découvrir qui a chargé le package que vous n'avez jamais demandé
Une seule ligne \listfiles dans le préambule fait apparaître à la fin du .log tous les fichiers réellement chargés ; quant à savoir qui a fait entrer chacun d'eux, c'est l'imbrication des parenthèses du journal qui répond. Un ( ouvre un fichier et ) le referme : si le ( qui ouvre xcolor.sty se trouve à l'intérieur des parenthèses de pgfcore.sty, c'est pgf qui l'a entraîné. Mesuré : un article nu lit 3 fichiers, une ligne de tikz porte le total à 34, et xcolor en fait partie ; hyperref à lui seul en apporte 30. « Je n'ai jamais écrit xcolor et j'obtiens un option clash » trouve presque toujours sa réponse dans cette liste. Pour une piste plus fine, -recorder inscrit chaque fichier ouvert dans 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)
***********Ordre de chargement : pourquoi hyperref va près de la fin, et ce qui vient après
hyperref se charge près de la fin parce qu'il récrit quantité de mécanismes — \ref, \cite, \caption, la table des matières, l'index — et une récriture doit porter sur la définition finale. Si quelque chose redéfinit ensuite la même chose, le travail de hyperref est purement et simplement effacé. Mais la règle dit « près de la fin », pas « en dernier ». Les packages bâtis sur ce que fait hyperref doivent évidemment venir après lui : bookmark, cleveref, hypcap et glossaries sont les plus courants. cleveref en particulier détecte lui-même l'infraction et lève une erreur, si bien qu'une inversion se voit immédiatement ; ses exigences précises sont traitées sur la page des références non définies.
Une chose mérite d'être dite nettement. Une grande part du folklore du type « A doit précéder B » ne produit strictement aucun effet sur TeX Live 2024. Essayer float avec hyperref, geometry avec hyperref, algorithm avec hyperref, bookmark avec hyperref et glossaries avec hyperref dans les deux ordres n'a donné, dans aucun cas, ni erreur ni avertissement ; les packages ont accumulé du code de compatibilité au fil des ans. Les règles d'ordre à respecter sont donc celles qu'énonce le manuel du package concerné, et remanier un préambule pour satisfaire une affirmation d'origine inconnue est en général du temps perdu. L'habitude de placer hyperref près de la fin reste néanmoins bonne, car elle découle de la nature même de la récriture et non d'une rumeur.
La différence entre \usepackage et \RequirePackage
Dans le préambule, les deux sont littéralement la même chose : lors du traitement de \documentclass, latex.ltx exécute \let\usepackage\RequirePackage, si bien qu'à partir de là il s'agit d'une seule commande. La différence n'existe qu'avant \documentclass, et à l'intérieur des fichiers .sty et .cls. À ces endroits, \usepackage s'arrête sur ! LaTeX Error: \usepackage before \documentclass. — le \usepackage du niveau format n'est défini que pour produire ce diagnostic. C'est pourquoi un package ou une classe écrits soi-même emploient \RequirePackage, et pourquoi la combinaison avec \PassOptionsToPackage permet d'injecter une option au-dessus de \documentclass. Lorsqu'une classe veut transmettre telles quelles ses propres options à un package qu'elle charge, \RequirePackageWithOptions est là pour cela.
% 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 optionsPaires qui refusent réellement de cohabiter, vérifiées sur TeX Live 2024
Au-delà des options, certaines paires ne peuvent coexister parce qu'elles définissent deux fois la même mécanique. Elles sont moins nombreuses que ne le laisse croire le folklore, et le symptôme n'est pas toujours une erreur au chargement. Celle qui refuse franchement est biblatex avec natbib : la compilation s'arrête sur ! Package biblatex Error: Incompatible package 'natbib'. — et si l'on ne voulait que \citet et \citep, \usepackage[natbib=true]{biblatex} les fournit. Le cas gênant est celui qui casse en silence : charger à la fois subfigure et subcaption ne provoque aucune erreur. L'ennui apparaît bien plus tard, sous la forme ! Missing number, treated as zero. à la ligne où l'on a écrit \begin{subfigure}{0.4\textwidth}, parce que \begin{subfigure} est absorbé par l'ancienne commande \subfigure définie par subfigure et lu tout autrement.
| Paire | Ce qui se passe réellement sur TeX Live 2024 |
|---|---|
biblatex + natbib | s'arrête aussitôt sur une erreur ; tout réunir en \usepackage[natbib=true]{biblatex} |
natbib + biblatex | dans cet ordre, aucune erreur, seulement des avertissements sur la redéfinition de \citeauthor et consorts |
subfigure + subcaption | les deux se chargent sans broncher ; plus tard \begin{subfigure} casse et signale des erreurs sans rapport apparent |
subfig + subcaption | les deux se chargent, mais subcaption renonce à définir son environnement, d'où ! LaTeX Error: Environment subfigure undefined. |
caption + subfigure | plus de conflit ; le .log note seulement Package caption Info: subfigure package is loaded. |
cleveref + hyperref | charger cleveref en premier interrompt la compilation ; il doit venir après hyperref et varioref |
cite + natbib | pas d'erreur, mais natbib avertit que cite ne devrait pas être employé avec lui ; n'en garder qu'un |
La leçon à tirer de ce tableau est de cesser de croire sur parole qu'« A et B sont incompatibles » et de construire un document de cinq lignes pour vérifier. L'incompatibilité de caption avec subfigure fut réellement une erreur ; elle est aujourd'hui rétrogradée en Info. À l'inverse, subfigure avec subcaption est le cas le plus net où « ça a chargé sans erreur, donc tout va bien » est la conclusion dangereuse. Le symptôme s'est déplacé de l'erreur au chargement vers une erreur bien plus tardive et d'apparence étrangère — voilà où en est l'incompatibilité des packages sur TeX Live 2024, et c'est précisément pourquoi l'habitude de poser \listfiles et de lire le .log est payante.