# Cannot modify header information – headers already sent by

> « Cannot modify header information – headers already sent by » : lisez « output started at » et supprimez l’espace, le BOM ou l’echo parasite.

- Auteur : WordPress Développement
- Publié le : 2026-10-02
- Mis à jour le : 2026-10-02
- URL : https://www.wpmoderne.fr/erreurs-wordpress/headers-already-sent/

> 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

1. **Un espace, une tabulation ou une ligne vide** avant la balise `<?php`, ou après un `?>` de fin de fichier.
2. **Une marque BOM** (trois octets invisibles) ajoutée par un éditeur qui enregistre en « UTF-8 avec BOM ».
3. **Une sortie de débogage oubliée** : `echo`, `print_r()`, `var_dump()` avant une redirection.
4. **Un avertissement ou une notice PHP affichés à l’écran**, qui provoquent à leur tour le message.
5. **Un fichier mal enregistré ou mal transféré** (FTP en mode texte, éditeur de texte inadapté).
6. **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](https://www.wpmoderne.fr/extensions/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](https://www.wpmoderne.fr/themes/ligne-vide-avant-php-functions-redirection-ignoree/).

### 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](https://www.wpmoderne.fr/erreurs-wordpress/erreur-syntaxe-php/).

### 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](https://www.wpmoderne.fr/themes/encodage-fautif-fichier-mo-sortie-parasite/). 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](https://www.wpmoderne.fr/extensions/register-activation-hook-erreurs-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
