Une page blanche, un import qui s’arrête au milieu, et ce message dans les logs : « Allowed memory size of 134217728 bytes exhausted ». Augmenter la limite fait parfois disparaître l’erreur… jusqu’à la prochaine fois. Dans ce guide, tu comprends ce que signifie vraiment l’erreur Allowed memory size exhausted en PHP, comment trouver la ligne qui consomme la mémoire, et comment la corriger durablement.
Le message complet ressemble à ceci :

PHP Fatal error: Allowed memory size of 134217728 bytes exhausted
(tried to allocate 20480 bytes) in /var/www/html/import.php on line 42TexteL’erreur Allowed memory size exhausted est l’une des erreurs fatales les plus courantes en PHP. Elle surprend parce que le script fonctionnait très bien… avec moins de données. Elle apparaît typiquement lors d’un import CSV, d’un export, du traitement d’images, dans WordPress après l’installation d’une extension, ou pendant un composer update.
La tentation est grande de simplement augmenter la limite. Parfois c’est la bonne solution, souvent c’est un pansement. Voyons comment faire la différence.

- Lire et comprendre chaque partie du message d’erreur.
- Trouver la limite actuelle et la modifier au bon endroit.
- Mesurer la consommation de mémoire de ton script.
- Corriger les causes réelles : gros tableaux, fichiers, requêtes SQL, boucles infinies.
- Régler les cas particuliers de WordPress et de Composer.
Que signifie l’erreur Allowed memory size exhausted ?
Chaque script PHP dispose d’une limite de mémoire, définie par la directive memory_limit du php.ini. C’est un garde-fou : sans elle, un seul script mal écrit pourrait consommer toute la mémoire du serveur et faire tomber tous les sites qu’il héberge.
Quand ton script essaie d’utiliser plus de mémoire que la limite, PHP l’arrête immédiatement avec une erreur fatale. Décortiquons le message :
| Partie du message | Signification |
|---|---|
Allowed memory size of 134217728 bytes | La limite actuelle : 134 217 728 octets = 128 Mo |
exhausted | La limite est atteinte |
tried to allocate 20480 bytes | La dernière demande de mémoire, celle qui a fait déborder le vase (ici 20 Ko) |
in /var/www/html/import.php on line 42 | Le fichier et la ligne où la limite a été dépassée |
Le message indique où la mémoire a débordé, pas forcément où elle a été consommée. Si un tableau grossit pendant toute une boucle, la limite peut être atteinte sur n’importe quelle ligne anodine. La petite valeur « tried to allocate 20480 bytes » est un indice : c’est l’accumulation qui pose problème, pas cette allocation-là.
Quelques conversions utiles pour lire les messages :
| Octets dans le message | Limite |
|---|---|
| 33554432 | 32 Mo |
| 67108864 | 64 Mo |
| 134217728 | 128 Mo (valeur par défaut de PHP) |
| 268435456 | 256 Mo |
| 536870912 | 512 Mo |
Étape 1 : connaître la limite actuelle
Avant de modifier quoi que ce soit, vérifie la valeur réellement appliquée :
# En ligne de commande
php -r "echo ini_get('memory_limit'), PHP_EOL;"
php --ini # affiche le php.ini utiliséBash<?php
// Dans une page web (la configuration peut être différente de la ligne de commande !)
echo 'Limite : ' . ini_get('memory_limit');PHPSur beaucoup de serveurs Linux, il existe un php.ini pour la ligne de commande (/etc/php/8.x/cli/php.ini) et un autre pour PHP-FPM ou Apache (/etc/php/8.x/fpm/php.ini). Modifier le mauvais est l’erreur la plus fréquente : vérifie toujours la valeur depuis le contexte où l’erreur se produit.
Étape 2 : mesurer la consommation de mémoire
Pour savoir si ton script a besoin de 130 Mo ou de 3 Go (ce qui indiquerait un vrai problème), mesure-le. PHP fournit deux fonctions :
<?php
function memoire(string $etape): void
{
printf(
"%-25s actuelle : %6.1f Mo | pic : %6.1f Mo\n",
$etape,
memory_get_usage(true) / 1048576,
memory_get_peak_usage(true) / 1048576
);
}
memoire('Début');
$lignes = file('clients.csv'); // charge tout le fichier en mémoire
memoire('Après lecture du CSV');
$donnees = array_map('str_getcsv', $lignes);
memoire('Après analyse');PHPDébut actuelle : 2.0 Mo | pic : 2.0 Mo
Après lecture du CSV actuelle : 86.0 Mo | pic : 86.0 Mo
Après analyse actuelle : 412.0 Mo | pic : 414.0 MoTexteLe coupable est immédiatement visible : transformer chaque ligne en tableau multiplie la mémoire par cinq. Un fichier CSV de 40 Mo peut facilement occuper plusieurs centaines de Mo une fois chargé dans des tableaux PHP, car chaque valeur et chaque élément de tableau a un coût supplémentaire.
Sur un gros projet, l’extension Xdebug (mode profile) ou des outils comme Blackfire et SPX montrent la consommation de mémoire de chaque fonction. Indispensable quand la fuite est cachée dans le code d’une librairie.
Étape 3 : corriger la cause réelle
Voici les causes les plus fréquentes de l’erreur Allowed memory size exhausted, et la bonne correction pour chacune.
Cause n°1 : charger un gros fichier d’un seul coup
file(), file_get_contents() ou json_decode() sur un gros fichier chargent tout en mémoire. Lis plutôt le fichier ligne par ligne :
<?php
// ❌ Tout le fichier en mémoire
$lignes = file('clients.csv');
foreach ($lignes as $ligne) {
traiter(str_getcsv($ligne));
}
// ✅ Une seule ligne en mémoire à la fois
$fichier = new SplFileObject('clients.csv');
$fichier->setFlags(SplFileObject::READ_CSV | SplFileObject::SKIP_EMPTY | SplFileObject::READ_AHEAD);
foreach ($fichier as $colonnes) {
traiter($colonnes);
}PHPAvec la seconde version, un fichier de 10 Go consomme autant de mémoire qu’un fichier de 10 Ko.
Cause n°2 : récupérer tous les résultats SQL avec fetchAll()
fetchAll() place tous les résultats dans un tableau. Sur une table d’un million de lignes, c’est l’erreur assurée.
<?php
// ❌ Un million de lignes dans un tableau
$clients = $pdo->query('SELECT * FROM clients')->fetchAll();
// ✅ Une ligne à la fois
$stmt = $pdo->query('SELECT id, email FROM clients');
while ($client = $stmt->fetch(PDO::FETCH_ASSOC)) {
traiter($client);
}PHPAttention : avec MySQL, PDO récupère par défaut tout le résultat côté client (requête bufferisée), même avec fetch(). Pour les très gros volumes, désactive ce mode ou traite par lots :
<?php
// Option A : requête non bufferisée (une seule requête à la fois sur cette connexion)
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
// Option B : traitement par lots de 1 000 lignes, basé sur l'identifiant
$dernierId = 0;
do {
$stmt = $pdo->prepare('SELECT id, email FROM clients WHERE id > ? ORDER BY id LIMIT 1000');
$stmt->execute([$dernierId]);
$lot = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($lot as $client) {
traiter($client);
$dernierId = $client['id'];
}
} while (count($lot) === 1000);PHPSELECT * ramène aussi les colonnes de texte long (descriptions, contenus HTML) dont tu n’as pas besoin. Lister les colonnes réduit la mémoire et accélère la requête.
Cause n°3 : accumuler des données dans une boucle
<?php
// ❌ Le tableau $resultats grossit à chaque tour
$resultats = [];
foreach (lireCommandes() as $commande) {
$resultats[] = calculerFacture($commande);
}
genererPdf($resultats);
// ✅ Un générateur : chaque élément est produit, utilisé, puis libéré
function factures(iterable $commandes): Generator
{
foreach ($commandes as $commande) {
yield calculerFacture($commande);
}
}
foreach (factures(lireCommandes()) as $facture) {
ecrireDansExport($facture);
}PHPLes générateurs (mot-clé yield) sont l’outil le plus puissant contre l’erreur de mémoire : au lieu de construire un énorme tableau, ils produisent les valeurs une par une, à la demande.
Cause n°4 : une boucle ou une récursion infinie
Si ton script consomme toujours toute la mémoire, quelle que soit la limite (128 Mo, 512 Mo, 2 Go…), ce n’est pas un problème de taille : c’est presque toujours une boucle infinie qui remplit un tableau, ou une récursion sans fin.
<?php
// ❌ Récursion infinie : une catégorie qui est sa propre parente
function cheminCategorie(array $categorie, array $toutes): array
{
$parent = $toutes[$categorie['parent_id']] ?? null;
return $parent ? [...cheminCategorie($parent, $toutes), $categorie['nom']] : [$categorie['nom']];
}
// ✅ On garde la trace des éléments déjà visités
function cheminCategorieSur(array $categorie, array $toutes, array $vus = []): array
{
if (isset($vus[$categorie['id']])) {
throw new RuntimeException('Boucle détectée dans les catégories');
}
$vus[$categorie['id']] = true;
$parent = $toutes[$categorie['parent_id']] ?? null;
return $parent
? [...cheminCategorieSur($parent, $toutes, $vus), $categorie['nom']]
: [$categorie['nom']];
}PHPAvec memory_limit = -1 (aucune limite), une boucle infinie consommera toute la mémoire du serveur, ralentira ou plantera les autres sites, et finira tuée par le système. La limite de mémoire est ton alliée : elle t’alerte vite.
Cause n°5 : le traitement d’images
Une photo JPEG de 4 Mo peut sembler légère, mais pour la redimensionner, GD la décompresse entièrement. Une image de 6 000 × 4 000 pixels occupe alors environ 6 000 × 4 000 × 4 octets, soit 96 Mo, et le double si tu crées une copie redimensionnée.
<?php
// Estimer la mémoire nécessaire avant de charger l'image
[$largeur, $hauteur] = getimagesize($chemin);
$memoireNecessaire = $largeur * $hauteur * 4 * 1.8; // marge pour la copie
if ($memoireNecessaire > 200 * 1048576) {
throw new RuntimeException('Image trop grande pour être traitée.');
}
$source = imagecreatefromjpeg($chemin);
$miniature = imagescale($source, 800);
imagejpeg($miniature, $destination, 85);
// Libérer la mémoire immédiatement (important dans une boucle)
imagedestroy($source);
imagedestroy($miniature);PHPLimite aussi la taille des images acceptées à l’envoi, ou utilise l’extension Imagick, plus économe sur les gros fichiers.
Cause n°6 : les scripts longs et les fuites de mémoire
Dans un script qui tourne longtemps (import nocturne, consommateur de file d’attente, while (true)), les petites accumulations finissent par compter : journaux en mémoire, cache d’un ORM, références circulaires entre objets.
<?php
foreach ($lots as $i => $lot) {
traiterLot($lot);
unset($lot); // libère la variable
if ($i % 100 === 0) {
gc_collect_cycles(); // force le nettoyage des références circulaires
$entityManager?->clear(); // vide le cache de Doctrine si tu l'utilises
}
}PHPPlutôt que de faire tourner un processus PHP pendant des heures, traite un nombre limité d’éléments puis termine le script : un gestionnaire comme Supervisor ou systemd le relance automatiquement, avec une mémoire toute neuve. C’est ce que font les workers de Laravel (--max-jobs) ou Symfony Messenger (--memory-limit).
Étape 4 : augmenter memory_limit, quand c’est justifié
Si tes mesures montrent qu’un traitement légitime a besoin de 200 Mo (une génération de PDF complexe, un gros export ponctuel), augmenter la limite est la bonne solution. Voici où le faire, du plus global au plus local :
| Méthode | Portée | Exemple |
|---|---|---|
php.ini | Tout le serveur (ou toute la version de PHP) | memory_limit = 256M |
| Pool PHP-FPM | Un site précis | php_admin_value[memory_limit] = 256M |
.htaccess (Apache + mod_php) | Un dossier | php_value memory_limit 256M |
.user.ini (PHP-FPM, CGI) | Un dossier | memory_limit = 256M |
ini_set() dans le code | Un script précis | ini_set('memory_limit', '512M'); |
| Ligne de commande | Une exécution | php -d memory_limit=1G import.php |
La méthode la plus fine est souvent la meilleure : augmente la limite uniquement pour le script qui en a besoin.
<?php
// export-annuel.php : ce script précis a besoin de plus de mémoire
ini_set('memory_limit', '512M');PHPLes modifications du php.ini ne sont prises en compte qu’au redémarrage de PHP-FPM ou d’Apache (sudo systemctl restart php8.4-fpm). Le fichier .user.ini, lui, est relu automatiquement, mais avec un délai (5 minutes par défaut). Sur un hébergement mutualisé, la limite se règle souvent dans le panneau de contrôle et ne peut pas dépasser le maximum de ton offre.
Le cas de WordPress
Dans WordPress, l’erreur apparaît souvent après l’installation d’une extension ou d’un thème lourd, ou dans l’administration. WordPress a sa propre limite, définie dans wp-config.php (avant la ligne « C’est tout, ne touchez pas à ce qui suit ! ») :
<?php
// wp-config.php
define('WP_MEMORY_LIMIT', '256M'); // partie publique du site
define('WP_MAX_MEMORY_LIMIT', '512M'); // administration (imports, mises à jour…)PHPCes valeurs ne peuvent pas dépasser le memory_limit du serveur. Si l’erreur persiste après une augmentation raisonnable, désactive les extensions une par une (ou renomme temporairement le dossier wp-content/plugins via FTP) pour trouver la responsable : une extension qui consomme 400 Mo a un problème, ce n’est pas à ton serveur de compenser.
Le cas de Composer
composer update peut consommer beaucoup de mémoire pour résoudre les dépendances d’un gros projet. Composer 2 est bien plus économe que Composer 1, mais tu peux lever sa limite pour une exécution :
# Linux / macOS
COMPOSER_MEMORY_LIMIT=-1 composer update
# Windows (PowerShell)
$env:COMPOSER_MEMORY_LIMIT = "-1"; composer updateBashIci, lever la limite est acceptable : c’est un outil de développement lancé ponctuellement, pas un script exposé aux visiteurs. Si tu utilises encore Composer 1, mets-le à jour avec composer self-update --2.
Récapitulatif : quelle solution pour quel cas ?
| Situation | Bonne solution |
|---|---|
| Import ou lecture d’un gros fichier | Lecture ligne par ligne (SplFileObject, fgets, fgetcsv) |
| Requête SQL avec beaucoup de lignes | fetch() en boucle, requête non bufferisée ou lots |
| Construction d’un gros tableau | Générateur (yield) |
| La mémoire explose quelle que soit la limite | Chercher une boucle ou une récursion infinie |
| Redimensionnement d’images | Limiter la taille, imagedestroy(), Imagick |
| Script qui tourne longtemps | unset(), gc_collect_cycles(), redémarrage régulier |
| Besoin légitime et mesuré | Augmenter memory_limit pour ce script uniquement |
| WordPress | WP_MEMORY_LIMIT et recherche de l’extension gourmande |
| Composer | COMPOSER_MEMORY_LIMIT=-1 et Composer 2 |

FAQ
Quelle valeur de memory_limit choisir ?
La valeur par défaut de PHP (128 Mo) suffit à la grande majorité des sites. 256 Mo est courant pour WordPress avec plusieurs extensions ou pour les frameworks. Au-delà de 512 Mo pour une page web, c’est le signe d’un code à optimiser plutôt que d’une limite trop basse.
Peut-on mettre memory_limit = -1 ?
Pour un outil en ligne de commande lancé ponctuellement (Composer, un script de migration surveillé), oui. Pour un site web, jamais : un seul script défaillant pourrait consommer toute la mémoire du serveur et faire tomber tous les sites qu’il héberge.
Quelle différence avec l’erreur « Out of memory » ?
« Allowed memory size exhausted » signifie que PHP a atteint sa propre limite (memory_limit). « Out of memory » signifie que le système n’a plus de mémoire à donner à PHP : le serveur lui-même est saturé, et c’est un problème d’infrastructure (trop de processus, pas assez de RAM).
L’erreur apparaît seulement en production, pourquoi ?
Soit la limite y est plus basse (vérifie avec ini_get('memory_limit') dans une page), soit il y a beaucoup plus de données qu’en local. Teste ton code avec un volume de données réaliste avant de le mettre en ligne.
Conclusion
L’erreur Allowed memory size exhausted n’est pas une fatalité, et augmenter la limite n’est qu’une solution parmi d’autres. La bonne démarche : lire le message, mesurer la consommation avec memory_get_peak_usage(), identifier la cause (fichier chargé d’un coup, fetchAll(), tableau qui grossit, boucle infinie, image géante), puis traiter les données en flux plutôt que tout en mémoire. Augmente memory_limit seulement quand un besoin légitime est mesuré, et seulement là où c’est nécessaire.
Pour tester tes scripts dans un environnement proche de la production, notre guide Docker pour développeur web te permet de reproduire la configuration de ton serveur sur ton poste. La documentation de memory_limit sur php.net détaille la directive et ses unités.

