L'11 giugno 2017 questo sito ha subito un downtime di diverse ore a causa di un errore piuttosto strano verificatosi all'interno del database di WordPress. Se vi siete imbattuti in questo articolo è molto probabile che il vostro sito sia stato colpito dalla medesima problematica. Se le cose stanno così, siete finiti nel posto giusto: farò del nostro meglio per aiutarvi a risolvere raccontandovi la mia esperienza.
Dal punto di vista dell'utente, l'anomalia si presentava come un classico errore HTTP 500 - Application Error che bloccava tutte le pagine non servite tramite cache. Come sempre in questi casi la prima cosa che ho fatto è stata abilitare gli appositi switch WP_DEBUG e WP_DEBUG_LOG presenti all'interno del file wp-config.php, che - come probabilmente sanno molti lettori - si trova nella cartella principale di WordPress contiene tutti i parametri di configurazione principali dell'installazione in uso.
1 2 3 |
// DEBUG switches - activate them to enable backup and backup log (in /wp-content/debug.log) define( 'WP_DEBUG', false); // shows the error on browser's screen define( 'WP_DEBUG_LOG', false); // writes the error in /wp-content/debug.log |
Come si può facilmente evincere dai commenti, il primo switch inserisce l'errore all'interno del HTTP response così da consentire all'utente di visualizzarlo on-screen, mentre il secondo - più sicuro - si limita a scriverlo all'interno di un file debug.log dedicato, anch'esso presente nella cartella principale di WordPress.
Questo era l'errore riportato:
Catchable fatal error: Object of class WP_Error could not be converted to string in /var/www/ryadel.com\wp-includes\rewrite.php on line 326
Sfortunatamente questa informazione non era sufficiente a comprendere cosa fosse davvero successo, ma se non altro puntava in una direzione chiara: ho quindi dato un'occhiata al codice sorgente del rewrite.php, fino a imbattermi nella seguente funzione (la linea 326 è quella evidenziata):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
/** * Filters the URL base for taxonomies. * * To remove any manually prepended /index.php/. * * @access private * @since 2.6.0 * * @param string $base The taxonomy base that we're going to filter * @return string */ function _wp_filter_taxonomy_base( $base ) { if ( !empty( $base ) ) { $base = preg_replace( '|^/index\.php/|', '', $base ); $base = trim( $base, '/' ); } return $base; } |
Il codice della funzione _wp_filter_taxonomy_base ha cominciato a fornirmi qualche informazione utile sul problema: a quanto pare lo script si aspettava di trovare un nome di categoria, quindi una stringa, trovando al suo posto - almeno a giudicare dal messaggio di errore - un oggetto di tipo WP_Error. Ma cosa ci fa un oggetto WP_Error al posto di un nome di categoria?
Per rispondere a questa domanda ho dato un'occhiata all'error log del PHP; lì, oltre a trovare una conferma ulteriore dei miei sospetti, ho potuto recuperare un'altra informazione estremamente interessante - avvenuto immediatamente prima del verificarsi dell'errore oggetto dell'indagine - che mi ha aiutato a comprendere cosa fosse realmente avvenuto:
1 2 3 4 5 6 7 8 9 10 |
[10-Jun-2017 22:26:13 UTC] PHP Warning: mysqli_query(): (HY000/6): Error on delete of 'C:\Windows\SERVIC~2\NETWOR~1\AppData\Local\Temp\#sql20c_985bf_0.MYI' (Errcode: 13 - Permission denied) in /var/www/ryadel.com\wp-includes\wp-db.php on line 1877 [10-Jun-2017 22:26:13 UTC] WordPress database error Error on delete of 'C:\Windows\SERVIC~2\NETWOR~1\AppData\Local\Temp\#sql20c_985bf_0.MYI' (Errcode: 13 - Permission denied) for query SHOW FULL COLUMNS FROM `wp_options` made by require(...) [10-Jun-2017 22:26:18 UTC] PHP Catchable fatal error: Object of class WP_Error could not be converted to string in C:\<WP_PATH>wp-includes\rewrite.php on line 326 [10-Jun-2017 22:26:18 UTC] PHP Catchable fatal error: Object of class WP_Error could not be converted to string in C:\<WP_PATH>wp-includes\rewrite.php on line 326 [10-Jun-2017 22:26:20 UTC] PHP Catchable fatal error: Object of class WP_Error could not be converted to string in C:\<WP_PATH>wp-includes\rewrite.php on line 326 [10-Jun-2017 22:26:22 UTC] PHP Catchable fatal error: Object of class WP_Error could not be converted to string in C:\<WP_PATH>wp-includes\rewrite.php on line 326 [10-Jun-2017 22:26:22 UTC] PHP Catchable fatal error: Object of class WP_Error could not be converted to string in C:\<WP_PATH>wp-includes\rewrite.php on line 326 [10-Jun-2017 22:26:22 UTC] PHP Catchable fatal error: Object of class WP_Error could not be converted to string in C:\<WP_PATH>wp-includes\rewrite.php on line 326 [10-Jun-2017 22:26:23 UTC] PHP Catchable fatal error: Object of class WP_Error could not be converted to string in C:\<WP_PATH>\wp-includes\rewrite.php on line 326 [10-Jun-2017 22:26:24 UTC] PHP Catchable fatal error: Object of class WP_Error could not be converted to string in C:\<WP_PATH>\wp-includes\rewrite.php on line 326 |
Il quadro cominciava a prendere forma: PHP doveva aver incontrato un problema durante un tentativo di scrittura su disco, magari dovuto a una temporanea indisponibilità del FileSystem: in conseguenza dell'anomalia, la funzione in questione - che in condizioni normali dovrebbe restituire un category name - aveva restituito un oggetto WP_Error, che era poi stato serializzato e memorizzato sul DB in luogo della stringa medesima. La causa dell'errore era quindi interamente da ricondurre alla presenza di quella "stringa anomala" nel DB al posto di un nome di categoria.
Il passo successivo che ho dovuto compiere è stato quello di individuare la tabella e la riga oggetto dell'anomalia: la tabella, WP_Options, era già presente nel file di log PHP: mi è bastato aprirla con SQLyog (se non sapete cos'è, leggete qui) per capire quale fosse il valore errato: nel mio caso si trattava della chiave category_base, contenuto per l'appunto nella tabella wp_options.
Ecco cosa c'era dentro al valore della colonna in questione in luogo del nome della categoria:
Una volta identificato il problema, non è stato difficile procedere con la soluzione: è bastato cancellare tutto il contenuto della chiave category_base di quella determinata riga per risolvere il problema, ripristinando le funzionalità del sito.
Questo è quanto: speriamo che questa breve guida vi aiuti a risolvere questo annoso problema!