Magento 2 missing bin/magento, lib, dev and setup directories
If you’ve ever pulled a Magento 2 project and found bin/magento, lib/, dev/ or setup/ simply aren’t there, you’re not going crazy - those directories are deployed out of the magento/magento2-base package by Composer rather than living in the repo. When that deploy step doesn’t run, or runs partially, the files never land and you’re left staring at a project that looks half-installed.
The fix
In most cases a reinstall of the base package re-triggers the deploy and the missing directories reappear:
composer reinstall magento/magento2-base
That forces Composer to remove and re-add the package, which runs the magento-composer-installer deploy step again and copies the mapped files back into place. Worth running bin/magento afterwards to confirm the CLI is back.
Why it happens
The deploy is handled by magento/magento-composer-installer, and there’s a fairly nasty bug in its copy strategy. The Copy::createDelegate() method uses file_exists(), which dereferences symlinks - so when a symlink with a missing target sits at one of the mapped destination paths, the installer reads it as absent, tries to mkdir() over the existing link node and hits a silent File exists error.
The worse part is the error swallowing. DeployManager::doDeploy() catches the ErrorException but only logs it under -vvv verbosity, so the remaining mappings get skipped with no warning. The install reports success while setup/ and friends are partially or completely empty.
I’ve raised a Github issue with the full reproduction. There’s also a longstanding PR against magento-composer-installer that removes the exception suppression so composer install fails loud and early instead of leaving you with a broken-but-apparently-fine install - it’s been open for years awaiting review.
So if the reinstall doesn’t stick, check for a dangling symlink at the target paths before assuming Composer is at fault.
Found this useful? Everything here is free and stays that way. If it saved you an afternoon, you can buy me a coffee.