Warning: Cannot modify header information - headers already sent by (output started at /chemin/fichier.php:1)
En anglais : Warning: Cannot modify header information - headers already sent by (output started at /path/file.php:1)
Réponse rapide
Du texte a été envoyé au navigateur avant les en-têtes HTTP (redirection, cookie). Le message « output started at » indique le fichier et la ligne coupables : retirez l’espace, la marque BOM ou l’affichage de débogage qui s’y trouve.
En haut d’une page, ou à la place d’une redirection qui ne se fait pas, PHP affiche un avertissement : « Warning: Cannot modify header information - headers already sent by (output started at /…/wp-config.php:42) in /…/pluggable.php on line 1542 ». Il apparaît souvent à la connexion (le formulaire se recharge au lieu de vous mener au tableau de bord), à l’enregistrement d’un formulaire, ou juste après l’activation d’une extension. Il peut toucher le site public, l’administration, ou la page de connexion.
Ce n’est pas une erreur fatale : le site continue de s’afficher. Mais tout ce qui dépend des en-têtes HTTP (redirections, cookies de connexion, types de contenu) échoue silencieusement. Le message contient d’ailleurs, sans que cela saute aux yeux, la solution : le fichier et la ligne qui ont envoyé du texte trop tôt.
Ce que signifie cette erreur
Une réponse HTTP est composée d’abord d’en-têtes (statut, cookies, Location pour une redirection…), puis du corps de la page. Dès que PHP envoie le premier octet du corps, les en-têtes partent et ne peuvent plus être modifiés. Si du code appelle ensuite header() ou setcookie(), PHP émet l’avertissement. Le cœur de WordPress fait cet appel dans wp_redirect() (wp-includes/pluggable.php, qui envoie header( "Location: …" )) et dans la fonction qui pose les cookies d’authentification.
Le message contient deux emplacements. Celui qui suit « output started at » désigne l’endroit où la sortie a commencé : c’est le coupable. Celui qui suit « in … on line » désigne le code qui a tenté d’envoyer l’en-tête : c’est la victime, souvent un fichier du cœur. Cherchez donc toujours la cause dans le premier. La fonction PHP headers_sent(), que WordPress consulte à plusieurs endroits, permet de savoir si les en-têtes sont déjà partis.
Lors de l’activation d’une extension, WordPress compte les caractères inattendus produits et affiche : « Cette extension a généré N caractères de sortie inattendus lors de son activation. » Le texte ajoute que, si vous remarquez des messages « headers already sent », vous devriez désactiver ou supprimer cette extension (wp-admin/plugins.php).
Diagnostic rapide
| Symptôme / constat | Cause probable | À vérifier |
|---|---|---|
| « output started at … :1 » (ligne 1) dans un fichier PHP | Espace, ligne vide ou BOM avant <?php | Début du fichier en hexadécimal |
| « output started at » pointe la dernière ligne d’un fichier | Espace ou retour à la ligne après ?> | Fin du fichier ; supprimer la balise fermante |
Le fichier cité est wp-config.php ou functions.php | Modification manuelle récente avec un caractère parasite | Dernière modification, début et fin du fichier |
| Un autre avertissement ou une « Notice » s’affiche juste avant | L’affichage des erreurs PHP produit lui-même la sortie | WP_DEBUG_DISPLAY, display_errors |
Le fichier est un .mo ou un fichier de traduction | Encodage fautif du fichier de traduction | Régénérer le fichier de langue |
| Le problème apparaît seulement à l’activation d’une extension | Sortie produite par l’extension à son chargement | Fichier principal de l’extension |
Les causes les plus fréquentes
- Un espace, une tabulation ou une ligne vide avant la balise
<?php, ou après un?>de fin de fichier. - Une marque BOM (trois octets invisibles) ajoutée par un éditeur qui enregistre en « UTF-8 avec BOM ».
- Une sortie de débogage oubliée :
echo,print_r(),var_dump()avant une redirection. - Un avertissement ou une notice PHP affichés à l’écran, qui provoquent à leur tour le message.
- Un fichier mal enregistré ou mal transféré (FTP en mode texte, éditeur de texte inadapté).
- Une redirection lancée trop tard dans un gabarit de thème, après
get_header().
Solutions pas à pas
Faites une copie des fichiers que vous allez modifier. Du moins invasif au plus technique :
1. Lire « output started at »
Relevez le chemin et le numéro de ligne qui suivent « output started at ». Ouvrez ce fichier dans un éditeur qui affiche les caractères invisibles. Si la ligne est la première (:1), le problème se situe avant la balise <?php. Notre article « headers already sent » : trouver la cause détaille un cas réel.
2. Supprimer les espaces et la balise fermante
Dans un fichier contenant uniquement du PHP, la balise ?> de fin est facultative et déconseillée : supprimez-la, ainsi que toute ligne vide après la dernière instruction. Vérifiez aussi qu’aucun caractère ne précède <?php, qui doit être le premier du fichier. Pour repérer les fichiers dont une ligne se termine par une balise fermante :
grep -rln '?>[[:space:]]*$' --include=*.php wp-config.php wp-content/themes/mon-theme wp-content/plugins/mon-extension
Ouvrez ensuite les fichiers listés et contrôlez leur dernière ligne. Le cas typique d’un functions.php modifié par plusieurs personnes est illustré dans l’article sur la redirection ignorée à cause d’une ligne vide.
3. Retirer la marque BOM
Un BOM ne se voit pas à l’écran. Recherchez les fichiers qui en contiennent, puis supprimez-le :
grep -rlI $'\xEF\xBB\xBF' --include=*.php wp-config.php wp-content/themes wp-content/plugins
sed -i '1s/^\xEF\xBB\xBF//' wp-content/themes/mon-theme/functions.php
La seconde commande (sed GNU, sous Linux) retire les trois octets en début de fichier ; sauvegardez le fichier avant. Dans votre éditeur, choisissez ensuite l’encodage « UTF-8 sans BOM ». Si le BOM vient d’un transfert FTP en mode texte, il peut aussi provoquer une erreur de syntaxe : voir la fiche Parse error: syntax error.
4. Masquer les avertissements affichés à l’écran
Si l’avertissement qui précède est lui-même une notice ou un « Deprecated » affiché, cachez l’affichage tout en le gardant dans le journal. Dans wp-config.php, au-dessus de la ligne « That’s all, stop editing! » :
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
@ini_set( 'display_errors', 0 );
Lisez ensuite wp-content/debug.log et corrigez l’origine de l’avertissement : masquer ne corrige pas le code. En production, laissez WP_DEBUG à false une fois le diagnostic terminé.
5. Corriger le moment de la redirection (développeurs)
Une redirection doit partir avant toute sortie, depuis un hook précoce et suivie d’un exit, jamais depuis un gabarit déjà en cours d’affichage :
add_action( 'template_redirect', function () {
if ( is_page( 'ancienne-page' ) ) {
wp_safe_redirect( home_url( '/nouvelle-page/' ), 301 );
exit;
}
} );
Pour une action déclenchée dans l’administration, utilisez admin_init ou le hook propre à l’action. Avant d’appeler wp_redirect() dans du code dont vous ignorez le contexte, vous pouvez tester headers_sent() et passer à un affichage de secours si la valeur est vraie.
6. Isoler l’extension ou le thème fautif
Si le fichier cité est un fichier de traduction (.mo), voir l’article sur l’encodage fautif d’un fichier .mo. S’il fait partie d’une extension, désactivez-la en renommant son dossier dans wp-content/plugins/ par SFTP, ou avec wp plugin deactivate nom-de-l-extension. Une extension qui bute sur ce problème dès son activation est détaillée dans l’article register_activation_hook : les erreurs qui cassent l’activation. Pour vérifier que tout est réglé, rechargez la page en navigation privée : l’avertissement doit avoir disparu et la redirection doit fonctionner. Côté ligne de commande :
curl -s https://www.exemple.fr/wp-login.php | head -c 120 | xxd
La réponse doit commencer directement par <!DOCTYPE html> (octets 3c 21 44 4f…), sans octet ni avertissement avant.
Sans accès à l’administration
Utilisez SFTP ou le gestionnaire de fichiers de l’hébergeur pour corriger le fichier désigné par « output started at ». Si la connexion est bloquée par le message, ce fichier est presque toujours wp-config.php ou functions.php : contrôlez leur début et leur fin.
Prévenir l’erreur
- Omettez la balise
?>finale dans tous vos fichiers PHP purs. - Configurez votre éditeur sur « UTF-8 sans BOM » et sur l’affichage des caractères invisibles.
- Désactivez l’affichage des erreurs en production et gardez-les dans
debug.log. - Transférez les fichiers en mode binaire (ou via SFTP, Git ou une méthode de déploiement) pour qu’aucun caractère ne soit réécrit.
- Relisez les fichiers touchés par des collègues ou des outils automatiques : un contrôle de style (PHPCS) détecte les espaces parasites avant la mise en ligne.
Questions fréquentes
Ce message est-il dangereux pour mon site ?
Non, c’est un avertissement. Mais il signale que des redirections ou des cookies échouent : on ne peut plus se connecter, ou un formulaire ne renvoie pas vers la bonne page. Mieux vaut le corriger rapidement (voir aussi la fiche cookies bloqués si la connexion échoue).
Le message désigne un fichier du cœur de WordPress. Dois-je le modifier ?
Non. Le fichier qui suit « in » est celui qui a tenté d’envoyer l’en-tête, pas celui qui a produit la sortie. Cherchez le fichier cité après « output started at ».
Pourquoi l’erreur disparaît-elle quand je désactive WP_DEBUG ?
Parce que les avertissements affichés à l’écran étaient eux-mêmes la sortie qui bloquait les en-têtes. Le vrai défaut persiste : lisez le journal avec WP_DEBUG_LOG et corrigez-le.
Peut-on contourner le problème avec ob_start() ?
C’est possible en urgence, car la mise en tampon retarde l’envoi du corps de la page. Mais cela masque la cause et peut ralentir le site : corrigez plutôt le fichier qui produit la sortie.