J’ai récemment joué avec Composer pour gérer les dépendances d’un plugin WordPress, et il faut reconnaître que l’outil simplifie énormément la gestion du code tiers.
Lors d’un changement de Mac, après import de mes anciennes données sur une nouvelle machine, j’ai obtenu ce message d’erreur :
Composer: file_put_contents(./composer.json): failed to open stream: Permission deniedCode language: HTTP (http)
Cette erreur signifie que Composer essaie d’écrire dans composer.json, ou dans le dossier courant, mais que l’utilisateur qui exécute la commande n’a pas les droits nécessaires.
Le problème peut venir du dossier du projet, du fichier composer.json, du cache Composer, du dossier global Composer, ou d’un ancien usage de sudo composer qui a laissé des fichiers appartenant à root.
Comprendre l’erreur
Le message important est :
failed to open stream: Permission denied
Composer n’arrive pas à écrire dans le fichier demandé. Dans l’exemple :
file_put_contents(./composer.json)
Composer tente d’écrire dans composer.json, dans le dossier courant.
Cela arrive souvent après :
- une migration de Mac ou de PC ;
- une restauration depuis une sauvegarde ;
- un changement d’utilisateur système ;
- une commande Composer lancée avec
sudo; - un projet copié depuis un autre compte ;
- un dossier synchronisé via Dropbox, iCloud, NAS ou disque externe ;
- un projet créé dans un dossier appartenant à
rootou à un autre utilisateur.
Donc avant de corriger au marteau, on vérifie exactement quel dossier pose problème. Le marteau marche, certes, mais il a une mauvaise finesse de diagnostic.
Première vérification : suis-je dans le bon dossier ?
Commencez par vérifier le dossier courant :
pwd
Puis listez les droits du dossier et du fichier composer.json s’il existe :
ls -ld .
ls -l composer.json composer.lock 2>/dev/nullCode language: JavaScript (javascript)
Vous devez voir votre utilisateur comme propriétaire, par exemple :
drwxr-xr-x 12 matt staff 384 6 mai 10:42 .
-rw-r--r-- 1 matt staff 842 6 mai 10:42 composer.jsonCode language: CSS (css)
Si vous voyez root ou un ancien utilisateur, Composer ne pourra pas forcément écrire dans le projet.
Correction la plus fréquente : reprendre possession du dossier projet
Si le dossier du projet appartient à un autre utilisateur, corrigez uniquement ce dossier.
Depuis le dossier parent du projet :
sudo chown -R "$USER" mon-projetCode language: JavaScript (javascript)
Ou depuis le dossier du projet lui-même :
sudo chown -R "$USER" .Code language: JavaScript (javascript)
Sur macOS, on peut aussi préciser le groupe courant :
sudo chown -R "$USER":staff .Code language: JavaScript (javascript)
Sur Linux, le groupe porte souvent le même nom que l’utilisateur :
sudo chown -R "$USER":"$USER" .Code language: JavaScript (javascript)
Ensuite, relancez la commande Composer :
Vos mises à jour vous font peur ?
PHP 8.x qui casse un plugin, un thème qui n'est plus maintenu, une mise à jour de WooCommerce qui change tout — je gère les montées de version proprement, avec environnement de staging et rollback prévu.
Mettons votre stack à jour sans risque →composer install
ou :
composer require vendor/packageCode language: JavaScript (javascript)
Éviter la mauvaise correction : chown -R $USER ~
Dans l’ancienne version de cet article, je proposais :
sudo chown -R $USER ~/.composer/Code language: JavaScript (javascript)
Cette commande peut encore être utile si le problème vient vraiment du dossier Composer global. Mais elle ne corrige pas un projet dont le dossier courant appartient à root.
Évitez surtout les corrections trop larges du type :
sudo chown -R "$USER" ~Code language: JavaScript (javascript)
C’est brutal, lent, et parfois dangereux. Votre dossier personnel peut contenir des fichiers qui doivent appartenir à d’autres utilisateurs ou avoir des droits spécifiques. Corrigez le dossier exact qui pose problème, pas tout le royaume.
Vérifier le dossier global de Composer
Composer utilise un dossier global, souvent appelé COMPOSER_HOME, pour stocker sa configuration globale, ses plugins et certains fichiers liés à l’utilisateur.
Pour le localiser :
composer config --global homeCode language: PHP (php)
Selon votre système, il peut s’agir de :
~/.composer
~/.config/composer
/Users/votre-utilisateur/.composer
/Users/votre-utilisateur/.config/composer
Composer documente notamment COMPOSER_HOME comme le chemin utilisé pour stocker des éléments globaux comme config.json, et documente aussi les chemins de cache par défaut selon le système. Composer CLI : COMPOSER_HOME
Vérifiez les droits :
composer_home="$(composer config --global home)"
ls -ld "$composer_home"Code language: JavaScript (javascript)
Si ce dossier appartient à root, corrigez-le :
sudo chown -R "$USER" "$composer_home"Code language: JavaScript (javascript)
Sur Linux, avec le groupe utilisateur :
sudo chown -R "$USER":"$USER" "$composer_home"Code language: JavaScript (javascript)
Vérifier le cache Composer
L’erreur peut aussi venir du cache Composer, surtout si vous avez déjà lancé Composer avec sudo.
Pour connaître le chemin du cache :
composer config cache-dir
Composer documente cache-dir comme le dossier qui stocke les caches utilisés par Composer. Sur macOS, le cache se trouve par défaut dans /Users/<user>/Library/Caches/composer, et sur les systèmes Unix suivant XDG, dans $XDG_CACHE_HOME/composer. Composer config : cache-dir
Vérifiez les droits :
cache_dir="$(composer config cache-dir)"
ls -ld "$cache_dir"Code language: JavaScript (javascript)
Corrigez si nécessaire :
sudo chown -R "$USER" "$cache_dir"Code language: JavaScript (javascript)
Ou videz simplement le cache :
composer clear-cache
Ne pas lancer Composer avec sudo
Le piège classique consiste à corriger l’erreur ainsi :
sudo composer install
Oui, cela peut “marcher”. Mais cela crée souvent de nouveaux fichiers appartenant à root dans votre projet ou dans le cache Composer, et vous retrouvez le même problème plus tard.
Composer recommande fortement d’éviter d’exécuter Composer en super-utilisateur/root, car les plugins et scripts Composer peuvent exécuter du code tiers avec les droits de l’utilisateur qui lance la commande. Composer FAQ : exécuter Composer en root
Donc, en local ou sur un serveur classique, utilisez Composer avec votre utilisateur normal :
composer install
composer update
composer require vendor/packageCode language: JavaScript (javascript)
Réservez sudo aux opérations système : installer Composer globalement, déplacer un binaire dans /usr/local/bin, installer des paquets APT, etc.
Corriger les dégâts causés par sudo composer
Si vous avez lancé Composer avec sudo, commencez par chercher les fichiers appartenant à root dans le projet :
find . -user root -maxdepth 3 -printCode language: PHP (php)
Si vous confirmez que ces fichiers devraient appartenir à votre utilisateur, corrigez le projet :
sudo chown -R "$USER" .Code language: JavaScript (javascript)
Sur Linux :
sudo chown -R "$USER":"$USER" .Code language: JavaScript (javascript)
Puis corrigez Composer global et son cache si nécessaire :
composer_home="$(composer config --global home)"
cache_dir="$(composer config cache-dir)"
sudo chown -R "$USER" "$composer_home" "$cache_dir"Code language: JavaScript (javascript)
Ensuite seulement, relancez Composer sans sudo.
Cas macOS après migration de machine
Après une migration macOS, il arrive que certains dossiers gardent des permissions ou propriétaires incohérents.
Vérifiez votre utilisateur :
whoami
id
Dans le dossier du projet :
ls -ld .
ls -la | head
Si le projet appartient à un ancien utilisateur ou à root :
sudo chown -R "$USER":staff .Code language: JavaScript (javascript)
Vérifiez aussi le cache Composer macOS :
ls -ld "$HOME/Library/Caches/composer"Code language: JavaScript (javascript)
Et corrigez si nécessaire :
sudo chown -R "$USER":staff "$HOME/Library/Caches/composer"Code language: JavaScript (javascript)
Enfin, testez :
composer diagnose
Cas WordPress : thème ou plugin avec Composer
Dans un plugin ou thème WordPress, Composer est souvent utilisé pour charger des dépendances PHP, des outils de build, PHPStan, PHPCS, WPCS, Rector, Freemius SDK, ou une autoload PSR-4.
Dans ce cas, placez-vous à la racine du plugin ou du thème, là où se trouve composer.json :
cd wp-content/plugins/mon-plugin
composer install
Si l’erreur apparaît :
ls -ld .
ls -l composer.json composer.lock vendor 2>/dev/nullCode language: JavaScript (javascript)
Puis corrigez seulement le plugin concerné :
sudo chown -R "$USER" wp-content/plugins/mon-pluginCode language: JavaScript (javascript)
Sur un serveur de production, je préfère éviter de lancer composer update. On déploie plutôt un composer.lock testé, puis on lance :
composer install --no-dev --optimize-autoloader
composer update change les versions. composer install installe les versions verrouillées. Ce détail évite beaucoup de “mais ça marchait hier”.
Cas serveur web : utilisateur de déploiement et utilisateur PHP
Sur un serveur, évitez de faire appartenir tout le code à www-data si ce n’est pas nécessaire. Une approche courante consiste à avoir :
- un utilisateur de déploiement propriétaire du code ;
- un groupe partagé avec l’utilisateur web ;
- des permissions en lecture pour PHP ;
- des permissions d’écriture limitées aux dossiers qui en ont besoin.
Exemple simple :
sudo chown -R deploy:www-data /home/www/example.com/public_html
sudo find /home/www/example.com/public_html -type d -exec chmod 2755 {} \;
sudo find /home/www/example.com/public_html -type f -exec chmod 0644 {} \;
Pour WordPress, les dossiers d’uploads/cache peuvent nécessiter une stratégie spécifique. Mais Composer, lui, doit être lancé par l’utilisateur qui possède le projet ou par l’utilisateur de déploiement prévu.
Cas Docker
Dans Docker, les erreurs de permissions Composer viennent souvent d’un décalage entre l’utilisateur du conteneur et l’utilisateur de l’hôte.
Exemple :
docker run --rm -v "$PWD":/app -w /app composer installCode language: JavaScript (javascript)
Cette commande peut créer des fichiers appartenant à root sur l’hôte selon l’image utilisée.
Une méthode consiste à exécuter Composer avec votre UID/GID :
docker run --rm \
-u "$(id -u):$(id -g)" \
-v "$PWD":/app \
-w /app \
composer installCode language: JavaScript (javascript)
Ce n’est pas toujours suffisant selon l’image et le cache, mais cela évite déjà beaucoup de fichiers créés en root dans le projet.
Commandes de diagnostic Composer
Composer fournit quelques commandes utiles pour diagnostiquer l’environnement :
composer diagnose
composer config --list
composer config --global home
composer config cache-dir
composer --versionCode language: PHP (php)
Vous pouvez aussi vérifier l’utilisateur courant et les droits :
whoami
id
pwd
ls -ld .
ls -l composer.json composer.lock 2>/dev/nullCode language: JavaScript (javascript)
Dans 90 % des cas, ces commandes suffisent à trouver le dossier qui n’appartient pas au bon utilisateur.
Méthode de résolution étape par étape
Voici l’ordre que j’utilise pour corriger cette erreur proprement :
- Vérifier le dossier courant avec
pwd. - Vérifier le propriétaire du dossier avec
ls -ld .. - Vérifier
composer.json,composer.locketvendor. - Corriger uniquement le dossier projet si nécessaire.
- Vérifier
composer config --global home. - Vérifier
composer config cache-dir. - Corriger le cache Composer si nécessaire.
- Relancer Composer sans
sudo. - Exécuter
composer diagnose.
Mémo rapide
# Erreur typique.
Composer: file_put_contents(./composer.json): failed to open stream: Permission denied
# Vérifier où l’on se trouve.
pwd
whoami
id
# Vérifier les droits du projet.
ls -ld .
ls -l composer.json composer.lock vendor 2>/dev/null
# Corriger le dossier projet courant.
sudo chown -R "$USER" .
# macOS.
sudo chown -R "$USER":staff .
# Linux.
sudo chown -R "$USER":"$USER" .
# Trouver le dossier global Composer.
composer config --global home
# Corriger COMPOSER_HOME.
composer_home="$(composer config --global home)"
sudo chown -R "$USER" "$composer_home"
# Trouver le cache Composer.
composer config cache-dir
# Corriger le cache.
cache_dir="$(composer config cache-dir)"
sudo chown -R "$USER" "$cache_dir"
# Vider le cache.
composer clear-cache
# Diagnostic Composer.
composer diagnose
# Relancer sans sudo.
composer installCode language: PHP (php)
Conclusion
L’erreur file_put_contents(./composer.json): failed to open stream: Permission denied indique que Composer n’a pas le droit d’écrire dans le fichier ou le dossier ciblé.
La cause la plus fréquente est un problème de propriétaire après migration, restauration, copie de projet, ou exécution de Composer avec sudo.
La correction la plus propre consiste à reprendre possession du dossier concerné :
sudo chown -R "$USER" .Code language: JavaScript (javascript)
Si le problème vient du dossier global Composer ou du cache, corrigez-les séparément :
composer_home="$(composer config --global home)"
cache_dir="$(composer config cache-dir)"
sudo chown -R "$USER" "$composer_home" "$cache_dir"Code language: JavaScript (javascript)
Enfin, évitez de lancer Composer avec sudo dans vos projets. Cela donne l’impression de résoudre le problème, puis laisse derrière lui des fichiers appartenant à root. Composer est un excellent gestionnaire de dépendances ; inutile de lui donner les clés du royaume pour écrire un fichier JSON.
Besoin d'un coup de main ?
Ce bug qui traîne depuis des semaines, ce plugin qui casse votre mise en page, cette fonctionnalité que personne n'arrive à implémenter proprement — c'est exactement ce que je règle au quotidien depuis 20 ans.
Parlons de votre problème →
