"Errore HTTP" nel caricamento immagini su WordPress: l'albero decisionale che trova davvero la causa
Individua la causa reale dell'errore HTTP nel caricamento immagini di WordPress con un solo controllo, poi correggi il ramo giusto: firewall, memoria PHP, post_max_size o Imagick.
Pubblicato
“Errore HTTP” non è una causa. È l’uploader dei media che ammette di aver inviato il file al server e di aver ricevuto una risposta che non è riuscito a interpretare come esito positivo — e almeno sei guasti scollegati fra loro producono quelle stesse identiche due parole. Tirare a indovinare fra le sei è il motivo per cui c’è chi passa un pomeriggio ad alzare upload_max_filesize su un sito il cui vero problema è una regola del firewall.
La via d’uscita più rapida è una singola osservazione che divide le sei cause in due gruppi, più un controllo per ogni ramo.
Prima cosa: leggi la risposta vera
Apri gli strumenti per sviluppatori del browser, vai sulla scheda Rete e ricarica il file. Osserva la richiesta verso async-upload.php. Qualunque cosa torni indietro è la tua diagnosi.
| Cosa vedi | Cosa significa | Vai a |
|---|---|---|
| 403 o 406, corpo HTML | Firewall o mod_security ha rifiutato la richiesta | Ramo A |
| 500, oppure risposta vuota o corpo troncato | PHP è andato in crash o ha esaurito la memoria a metà processo | Ramo B |
| 413 | Il corpo della richiesta ha superato un limite del server | Ramo C |
| 200, ma il corpo non è JSON pulito | Un plugin o il tema ha stampato output prima della risposta | Ramo D |
| La richiesta non si completa mai / va in timeout | Limite di tempo di esecuzione, di solito con file grandi | Ramo B |
Quell’unica occhiata elimina buona parte dei consigli che trovi in rete. Se non riesci ad arrivare agli strumenti del browser, attiva prima i log in wp-config.php:
define( 'WP_DEBUG', true );
define( 'WP_DEBUG_LOG', true );
define( 'WP_DEBUG_DISPLAY', false );
Riproduci il caricamento, poi leggi wp-content/debug.log. Una riga di errore fatale ti indica il ramo senza giri di parole. Se la riga è ostica, incollala nel decodificatore dei log di errore: associa le firme fatali più comuni a ciò che si è rotto davvero.
Ramo A — una regola del firewall o di mod_security
Un 403 con una pagina HTML nel corpo significa che la richiesta non è mai arrivata a WordPress. Qualcosa davanti a lui — mod_security, Cloudflare, Wordfence, Sucuri o le regole dell’hosting stesso — ha deciso che quella POST sembrava sospetta.
Il controllo: disattiva temporaneamente ogni plugin di sicurezza e riprova il caricamento. Se non cambia nulla, la regola è a livello di server e serve che l’hosting guardi il log di audit di mod_security all’orario del caricamento fallito. Possono mettere in whitelist l’ID della regola specifica.
Sii onesto con te stesso sui consigli che troverai qui intorno. Gli snippet che ti dicono di incollare questo nell’.htaccess:
SecFilterEngine Off
SecFilterScanPOST Off
si riferiscono a mod_security 1.x, ormai praticamente estinto. Su un server moderno quelle direttive o non fanno nulla o generano un 500 che peggiora la situazione. Il mod_security moderno usa SecRuleEngine, e comunque la maggior parte degli hosting gestiti blocca gli override per directory. Chiedi all’hosting, non incollare.
Ramo B — limiti di memoria o di esecuzione di PHP
È il ramo più comune e quello con il segnale più chiaro: è intermittente. Lo stesso file passa al terzo tentativo, oppure una foto da 2MB fallisce mentre un PDF da 6MB vola. I limiti rigidi di configurazione falliscono sempre allo stesso modo. I problemi di memoria no, perché quanta ne è disponibile dipende da cos’altro sta facendo il server.
Perché proprio le immagini: WordPress non si limita a salvare il file, lo decomprime in pixel grezzi per generare ogni dimensione intermedia — medium_large, tutto ciò che è registrato con add_image_size, woocommerce_thumbnail se hai un negozio, più una copia -scaled se l’immagine supera big_image_size_threshold. Un JPEG da 12 megapixel occupa qualche MB su disco e circa 48MB in memoria, prima ancora del buffer di ridimensionamento. Un limite di 128MB sparisce in fretta.
Alzalo in wp-config.php, sopra la riga “stop editing”:
define( 'WP_MEMORY_LIMIT', '256M' );
define( 'WP_MAX_MEMORY_LIMIT', '512M' );
Il costo reale: WP_MEMORY_LIMIT non può superare quello che PHP stesso consente. Se il tuo hosting fissa memory_limit a 128M, questa costante è puramente decorativa. Controlla il valore reale in Strumenti → Salute del sito → Informazioni → Server, non quello che hai scritto tu. Se il tetto è il limite di PHP, solo l’hosting può alzarlo.
Ramo C — dimensione del file e limiti della richiesta
Controlla i numeri veri in Strumenti → Salute del sito → Informazioni → Gestione dei media. Due impostazioni contano, e in genere se ne cambia solo una:
upload_max_filesize— il tetto per il singolo file.post_max_size— il tetto per l’intero corpo della richiesta.
Se l’intera POST supera post_max_size, PHP scarta la richiesta prima che WordPress esegua una sola riga di codice. Non c’è nulla da restituire, quindi l’uploader riceve una risposta non interpretabile e dice “Errore HTTP”. post_max_size dovrebbe sempre essere comodamente più grande di upload_max_filesize.
Un dettaglio che vale la pena conoscere: quando un file supera soltanto upload_max_filesize, di solito l’uploader se ne accorge già nel browser e dice che il file supera la dimensione massima consentita — un messaggio più chiaro. Quindi un “Errore HTTP” secco punta più spesso a post_max_size o al Ramo B che all’impostazione che tutti alzano per prima.
Dove modificarle dipende dal tuo stack. Su Apache con mod_php funziona l’.htaccess:
php_value upload_max_filesize 64M
php_value post_max_size 128M
Su PHP-FPM, LiteSpeed o NGINX — cioè su gran parte dell’hosting moderno — quelle righe non fanno nulla e possono generare un 500. Usa invece il pannello delle impostazioni PHP dell’hosting o un file .user.ini. NGINX applica anche il proprio client_max_body_size, che solo l’hosting può alzare.
Ramo D — la libreria di elaborazione immagini (Imagick vs GD)
WordPress preferisce ImageMagick quando l’estensione PHP è presente e ripiega su GD. Sugli hosting condivisi ImageMagick è spesso il problema: il suo file di configurazione delle policy limita memoria, disco e area per operazione, e quando un ridimensionamento supera uno di quei limiti il processo muore senza un messaggio utile. Di solito lo noti sulle immagini grandi mentre quelle piccole funzionano — cosa che sembra il Ramo B ma non lo è.
Forza GD per verificare l’ipotesi:
add_filter( 'wp_image_editors', function ( $editors ) {
return array( 'WP_Image_Editor_GD' );
} );
Mettilo in functions.php o in un piccolo mu-plugin, riprova il caricamento e rimuovilo se non cambia nulla.
Il compromesso onesto: GD non è oggettivamente migliore. Tiene l’intera bitmap non compressa nella memoria di PHP, quindi sui file molto grandi può sbattere contro memory_limit proprio dove ImageMagick — che lavora in parte fuori dall’allocazione di PHP — sarebbe riuscito. Il passaggio può scambiare un fallimento con un altro. Trattalo prima come diagnosi e solo poi come soluzione.
Ramo E — permessi della cartella uploads
Raro sull’hosting gestito, comune subito dopo una migrazione o uno spostamento manuale del server. Se wp-content/uploads non è scrivibile dall’utente del web server, o se una sottocartella anno/mese appena creata ha ereditato il proprietario sbagliato, la scrittura fallisce.
ls -ld wp-content/uploads
ls -ld wp-content/uploads/2026/07
Le directory dovrebbero normalmente essere 755 e appartenere all’utente con cui gira PHP. Non impostare 777 solo perché lo dice un forum: risolve il sintomo rendendo la cartella scrivibile da ogni account presente sul server, il che su hosting condiviso è un’esposizione reale.
Ramo F — il nome del file
È il controllo più economico dell’elenco, quindi fallo presto anche se è il meno probabile. Rinomina il file usando solo lettere minuscole, numeri e trattini — niente accenti, apostrofi, e commerciali, # o caratteri non latini — e ricaricalo. I caratteri speciali ogni tanto fanno scattare una regola di sicurezza o si rompono su un filesystem con codifica diversa. Dieci secondi per escluderlo.
Cosa non fare
Non partire disattivando tutti i plugin. È invasivo e verifica soltanto il Ramo A e il Ramo D. La risposta di rete ti dice di più in cinque secondi.
Non aggiungere righe handler a caso nell’.htaccess. Gli snippet che circolano con direttive SetHandler o AddHandler presuppongono la configurazione PHP di un hosting specifico. Sullo stack sbagliato mandano giù tutto il sito con un 500.
Non considerare risolto un “al secondo tentativo è andato”. Il successo intermittente è la firma del Ramo B, e tornerà nel momento in cui il server sarà sotto carico o qualcuno caricherà qualcosa di più pesante.
Ancora bloccato?
Se la risposta è un 200 pulito con JSON valido e il caricamento fallisce comunque, la rottura avviene dopo che il file è arrivato — di solito un plugin agganciato alla catena di elaborazione degli allegati che genera un errore fatale, oppure un plugin di ottimizzazione che invia una richiesta a un servizio esterno che va in timeout. Attiva WP_DEBUG_LOG, riproduci il problema e passa l’errore fatale risultante nel decodificatore dei log di errore per vedere quale file e quale hook sono davvero responsabili.
FAQ
Domande
Cosa significa "Errore HTTP" quando carico immagini su WordPress?
Significa che l'uploader del browser ha inviato il file al server e ha ricevuto in risposta qualcosa che non è riuscito a interpretare come esito positivo. Il messaggio descrive il sintomo, non la causa. Un processo PHP andato in crash, un blocco del firewall, un 403 e una risposta vuota producono tutti le stesse identiche due parole.
Perché la stessa immagine a volte si carica e a volte no?
I fallimenti intermittenti indicano quasi sempre memoria o CPU esaurite, non un limite di configurazione. Ridimensionare una foto grande richiede un picco di memoria e, su hosting condiviso, la quantità disponibile cambia in base al carico del server. Un limite rigido come post_max_size invece fallisce sempre allo stesso modo.
Passare da Imagick a GD in WordPress risolve gli errori HTTP?
A volte, e solo per un ramo specifico. Su hosting condiviso ImageMagick è spesso limitato da un file di policy o da risorse basse, e fallisce dove GD riesce. GD però usa più memoria sui file molto grandi, quindi il passaggio può peggiorare i fallimenti dovuti alla memoria invece di risolverli.
Come capisco se il firewall dell'hosting sta bloccando il caricamento?
Apri gli strumenti di rete del browser, carica il file e guarda il codice di stato restituito da async-upload.php. Un 403 o un 406 con corpo HTML significa che un web application firewall o una regola mod_security ha rifiutato la richiesta. Un 500 o una risposta vuota indicano invece che PHP è andato in crash.
Aumentare upload_max_filesize risolve l'errore HTTP?
Solo se il file supera davvero i tuoi limiti, e di solito conta di più post_max_size. Se l'intero corpo della richiesta è più grande di post_max_size, PHP lo scarta prima ancora che WordPress entri in funzione e l'uploader non riceve nulla. Alzare l'uno senza l'altro lascia il problema esattamente dov'era.
Il nome di un file può causare un errore HTTP in WordPress?
Sì, anche se è il ramo più raro. Lettere accentate, apostrofi, e commerciali e alfabeti non latini possono far scattare una regola di sicurezza o rompere un percorso su un filesystem con codifica diversa. Rinominare il file usando solo lettere minuscole, numeri e trattini non costa nulla ed esclude questo ramo in una decina di secondi.