Errore Cannot modify header information: significato e fix

Errore 'Cannot modify header information': cosa significa

L’errore 'Cannot modify header information - headers already sent' è un classico di PHP/WordPress che indica un tentativo di modificare gli header HTTP dopo che il body della risposta è già stato inviato. In questa guida spieghiamo le cause comuni e come WP Error Monitor ti aiuta a localizzarle.

Perchè si verifica

PHP invia header automaticamente quando inizia a stampare output. Se dopo l’output un plugin/tema chiama header(), setcookie(), session_start() o wp_redirect(), PHP genera un warning. Su WordPress capita tipicamente perchè: 1) un file PHP ha BOM UTF-8 all’inizio, 2) c’è uno spazio o newline prima di

Indizio chiave nell’errore

Il messaggio cita due posizioni: la riga che HA causato l’output (es. functions.php:1) e la riga che ha provato a modificare l’header (es. wp-login.php:500). Devi correggere la prima, non la seconda. WP Error Monitor mostra entrambe e include una preview dei primi 100 byte del file in questione per facilitare l’individuazione di BOM/spazi.

Strumenti di diagnosi

Usa il comando 'file -b ' per verificare encoding (deve essere ASCII o UTF-8 senza BOM). Per rimuovere BOM in batch: 'find . -name "*.php" -exec sed -i "1s/^\xEF\xBB\xBF//" {} \;'. Editor moderni (VSCode, PhpStorm) hanno opzioni per salvare senza BOM.

Encoding e charset trappole

L’encoding del file PHP impatta direttamente questo errore. UTF-8 with BOM aggiunge 3 byte iniziali invisibili che PHP tratta come output. UTF-16 è incompatibile con PHP. Windows-1252 va bene ma può causare problemi con accenti. La regola e': UTF-8 without BOM, Unix line endings (LF non CRLF). Configura il tuo IDE per default: VSCode user settings con files.encoding utf8 e files.eol newline unix. Verifica file remoti con 'file -bi nome.php' che mostra MIME e charset.

Hook timing in WordPress

Capire l’ordine di esecuzione hook WordPress aiuta a evitare l’errore. Hook con output (template_redirect, wp_head, the_content) vengono dopo headers; hook precoci (plugins_loaded, init, wp_loaded) sono prima e possono inviare header. Se un plugin aggancia template_redirect e tenta wp_redirect dopo aver echo qualcosa, viene questo errore. Risoluzione: muovi la logica redirect su hook init o usa wp_safe_redirect con check headers_sent() prima.

Pre-commit hook per BOM detection

Il modo più efficace di prevenire questo errore è bloccarlo prima del commit. Configura pre-commit hook (via Husky per JS, lefthook o pre-commit Python) che lancia wp wpem scan-bom solo sui file PHP modificati: se trova BOM, blocca commit. Output chiaro: 'BOM detected in: wp-content/plugins/foo/init.php at line 1. Remove BOM before commit.' Il developer fixa subito senza dover scoprire l’errore in staging/prod. Configurazione lefthook esempio: nel .lefthook.yml, pre-commit run wpem-scan con files glob *.php. Bloccare a commit-time risparmia ore di debug downstream.

Workaround temporanei per emergenza

In caso di errore in produzione e impossibilità immediata di fixare il file colpevole, due workaround temporanei: 1) ob_start() in mu-plugin che bufferizza tutto l’output (nascosto l’errore ma rallenta lievemente), 2) header_remove() chiamato esplicitamente prima dei punti critici. Entrambi sono cerotti: la root cause resta. Best practice: applica il workaround per riportare il sito online, apri ticket interno per fix definitivo entro 24h, monitora WP Error Monitor per assicurarti che il workaround non nasconda altri problemi correlati.

Best practice riassuntive

Per evitare l’errore Cannot modify header information, segui questa checklist: 1) editor IDE configurato per salvare PHP in UTF-8 senza BOM, 2) .editorconfig nella root del progetto con charset=utf-8, 3) pre-commit hook con wp wpem scan-bom, 4) mai chiudere il tag PHP a fine file (?> trailing newline è la fonte principale di whitespace), 5) usa wp_redirect con check headers_sent() prima della chiamata, 6) muovi logica redirect/header da template_redirect a init. Seguendo queste sei pratiche, l’errore diventa praticamente impossibile.

Procedura passo-passo

  1. Apri WP Error Monitor e filtra 'message contains Cannot modify header'.
  2. Apri l’evento: prendi il file che ha generato output (prima posizione nel messaggio).
  3. Scarica il file via SFTP e aprilo con un'editor che mostra BOM/whitespace.
  4. Rimuovi BOM iniziale e qualunque whitespace prima di
  5. Verifica che il file NON finisca con ?> seguito da newline (best practice: non chiudere il tag PHP).
  6. Carica il file corretto e svuota OPcache.
  7. Riprova l’azione (login, redirect) e verifica che l’errore non si ripresenti.
  8. Configura il tuo IDE per salvare PHP in UTF-8 senza BOM.
  9. Sposta logica redirect/header da template_redirect a init quando possibile.

Errori comuni e come risolverli

  • BOM non visibile in editor: Usa hexdump -C file.php | head -1 da SSH per verificare i primi 3 byte (EF BB BF).
  • Errore solo su Windows: Probabile editor che salva con CRLF e BOM: cambia configurazione editor.
  • Errore sparisce e ritorna: Probabile plugin che genera output condizionalmente: cerca echo/print/var_dump nel bootstrap dei plugin attivi.
  • Files modificati via web editor con BOM: WordPress editor non gestisce BOM: meglio editare via SFTP.
  • Encoding diverso tra dev e prod: Imposta git attribute eol=lf e encoding=utf8 in .gitattributes.

Domande frequenti

D: Posso usare ob_start come workaround?
R: Sì, mettere ob_start() in mu-plugin nasconde l’errore ma è una pezza: meglio risolvere alla radice.

D: Perchè non chiudere il tag PHP?
R: Evita newline trailing che diventano output quando il file viene incluso prima di header().

D: WP Error Monitor traccia anche i warning?
R: Sì, se WPEM_CAPTURE_LEVEL include E_WARNING.

D: ob_start nasconde il problema?
R: Sì, ma è un palliativo: la root cause rimane e può emergere altrove.

D: Posso forzare encoding via header?
R: Sì con header Content-Type charset UTF-8, ma non risolve BOM nei file PHP.

Hai bisogno di aiuto?

Se vuoi affidare il monitoraggio WordPress al team di G Tech Group, scrivici tramite il modulo di contatto.

Hai trovato utile quest'articolo?