Composer : résoudre file_put_contents composer.json Permission denied

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 à root ou à 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 :

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
Distingo, le livret à 2%

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 :

  1. Vérifier le dossier courant avec pwd.
  2. Vérifier le propriétaire du dossier avec ls -ld ..
  3. Vérifier composer.json, composer.lock et vendor.
  4. Corriger uniquement le dossier projet si nécessaire.
  5. Vérifier composer config --global home.
  6. Vérifier composer config cache-dir.
  7. Corriger le cache Composer si nécessaire.
  8. Relancer Composer sans sudo.
  9. 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.

Gravatar for Matt Biscay

Je suis Matt Biscay, développeur WordPress & WooCommerce certifié chez Codeable, administrateur système et enseignant.

J’aide les entreprises à créer, optimiser et fiabiliser leurs sites WordPress avec une approche technique propre : performance, sécurité, maintenance, développement sur mesure et résolution de problèmes complexes.

Sur Skyminds, je partage des tutoriels WordPress, WooCommerce, Linux et administration système, avec des solutions testées sur des cas réels et pensées pour durer.

Découvrez mes services WordPress et WooCommerce.

Opinions