Fix: 'Cannot instantiate interface Magento\Eav\Api\AttributeRepositoryInterface' on Magento 2.4.8-p3 setup:upgrade
After a 2.4.7-p3 to 2.4.8-p3 upgrade, setup:upgrade throws 'Cannot instantiate interface AttributeRepositoryInterface'. The root cause is stale compiled DI. Here is the exact recovery recipe plus the extension audit to run if it returns.
You ran composer install, kicked off bin/magento setup:upgrade, and Magento blew up before the first patch:
“There is an error in /app/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php at line: 50 — Cannot instantiate interface Magento\Eav\Api\AttributeRepositoryInterface.”
This is a classic post-upgrade trap. The fix is short, but only if you understand why the ObjectManager is suddenly trying to build an interface like a regular class. Here is the exact recovery sequence, plus the deeper audit to run if the error survives the first pass.
What the error actually means
The trace begins inside Magento’s ObjectManager:
There is an error in /app/vendor/magento/framework/ObjectManager/Factory/Dynamic/Developer.php at line: 50
Cannot instantiate interface Magento\Eav\Api\AttributeRepositoryInterface
#0 .../ObjectManager.php(73): Developer->create('Magento\\Eav\\Api...')
#1 .../AbstractFactory.php(170): ObjectManager->get('Magento\\Eav\\Api...')
#2 .../AbstractFactory.php(276): AbstractFactory->resolveArgument(Array, 'Magento\\Eav\\Api...', NULL, 'attributeReposi...', 'Magento\\Catalog...')
Read the stack from bottom to top: a constructor argument typed AttributeRepositoryInterface $attributeRepository needs a concrete implementation. The ObjectManager looks up its preferences map (the merged result of every module’s etc/di.xml), expects to find a mapping to Magento\Eav\Model\AttributeRepository, and instead is told “just build the interface directly.” PHP cannot instantiate an interface — so it throws.
That mapping does still exist in vendor/magento/module-eav/etc/di.xml in 2.4.8-p3. So why does Magento not see it? Because Magento is not reading di.xml at runtime — it is reading the compiled result from your previous version’s generated/ tree.
Why this happens on a 2.4.7-p3 → 2.4.8-p3 upgrade
Three pieces of state survive a composer install:
generated/code— compiled proxies, factories, and interceptors keyed to the old class graph.generated/metadata— the compiled DI configuration (the mergeddi.xmlfrom the previous build).var/cache+var/page_cache— warmed Redis/file caches that include the old config dump.
When Adobe ships a patch release that touches DI — new arguments on a constructor, a refactored preference, a removed virtual type — the new vendor/ code expects a fresh map. The old compiled map has a hole where the new constructor argument resolution lands, and the ObjectManager falls through to create(InterfaceName) instead of create(ConcreteClass). The fix is to throw the stale compiled state away and let Magento rebuild it.
generated/ tree is a snapshot of 2.4.7-p3’s DI graph being asked to resolve 2.4.8-p3’s constructor signatures.The fix (copy-paste, in order)
From your Magento root, with the new vendor/ already installed by composer install:
# 1. Wipe every piece of stale state
rm -rf generated/code generated/metadata
rm -rf var/cache var/page_cache var/view_preprocessed var/di
# 2. Re-dump the autoloader so Composer maps the new vendor tree fresh
composer dump-autoload
# 3. Re-run the upgrade
bin/magento setup:upgrade
# 4. Production hosts only: compile DI + redeploy static + flush cache
bin/magento setup:di:compile
bin/magento setup:static-content:deploy -f en_US
bin/magento cache:flush
That is the whole recipe. On developer-mode local stores, steps 1–3 are enough — missing generated classes are built on the next request. On production hosts, you must run step 4 or the storefront renders without DI-compiled interceptors and with stale assets.
composer dump-autoload matters: if the old optimized classmap still points Magento\Eav\Model\AttributeRepository at a path that no longer exists (or points at a stale Proxy class), setup:di:compile will fail with a different but equally cryptic error. Re-dumping is cheap insurance.If the same error returns after the wipe
If setup:upgrade still throws “Cannot instantiate interface AttributeRepositoryInterface” on the rebuilt generated/ tree, the problem is no longer stale state — one of your installed extensions is overriding the EAV preference with a class that no longer exists. Run this audit:
# Find every <preference> against the AttributeRepositoryInterface across
# vendor + app/code so you can see which module last claimed it.
grep -R --include='di.xml' \
'AttributeRepositoryInterface' \
app/code vendor/*/module-* vendor/*/*-module 2>/dev/null
# Same search, but for any EAV-API interface (broader net for related errors)
grep -R --include='di.xml' \
'Magento\\Eav\\Api\\' \
app/code vendor 2>/dev/null
Walk the matches. Anything outside vendor/magento/ that points AttributeRepositoryInterface at a custom class is the suspect. Two common shapes:
- Removed class in the preference target. The vendor refactored their plugin in a recent release and dropped the override class, but did not remove the
<preference>tag. - Class extends a removed parent. The override class still exists but extends a Magento parent that Adobe deleted in 2.4.8. PHP autoload fails before the constructor is even reached.
Disable that extension in app/etc/config.php (set its value to 0), re-run the upgrade, confirm the error is gone, then file a compatibility ticket with the extension vendor.
Related errors that share this root cause
The same recipe recovers Magento from several differently-worded failures — all of them flavors of “ObjectManager has a stale view of the world”:
| Symptom | What is really stale | Recovery |
|---|---|---|
Cannot instantiate interface ... | generated/metadata — compiled DI map | Wipe generated/ + dump-autoload + setup:upgrade |
Proxy.php: No such file or directory | generated/code — compiled proxies | Two-pass autoload (non-optimized → di:compile → optimized) |
Class ... does not exist during di:compile | Composer classmap pointing at removed file | composer dump-autoload then retry |
Argument 1 passed to ... must be an instance of ... | Cached interceptor built against old constructor | Wipe generated/ + cache:flush |
Make this less painful next time
The cleanest long-term fix is to stop relying on the host’s generated/ tree being correct across upgrades. Two changes pay for themselves:
- Build → deploy pipeline. Run
composer install,setup:di:compile, andsetup:static-content:deployin a fresh build container, package the resultingvendor/+generated/+pub/static/, and rsync the package to production. The live host never compiles — it only swaps in a known-good artifact. - Use
--keep-generatedon deploy. If your build step already producedgenerated/, runbin/magento setup:upgrade --keep-generatedso the upgrade does not discard the freshly compiled tree.
For a deeper look at what each phase of setup:upgrade actually does — declarative schema, the patch_list / setup_module tables, and the difference between developer and production mode — see What Magento setup:upgrade Actually Does. For the broader catalogue of universal upgrade traps (PHP, composer, Hyvä theme, indexer), see Magento 2.4.9 upgrade issues: 5 universal traps.
An upgrade that won’t finish, a generated/ tree that keeps regenerating broken, or extensions throwing DI errors you can’t trace? I am an Adobe-certified Magento & Hyvä developer — I debug 2.4.x → 2.4.y upgrades end to end. Fixed-fee from $499 audit · $2,499 sprint · ~4h @ $25/hr for this kind of recovery.
Frequently asked questions
Why does Magento say it cannot instantiate Magento\Eav\Api\AttributeRepositoryInterface?
Magento’s ObjectManager tried to build a concrete implementation for that interface but found no preference pointing at one. Almost every time on 2.4.8-p3 this happens immediately after a version upgrade and the real cause is a stale generated/ tree from your previous release — the compiled DI map is out of sync with the new vendor code. Wipe generated/, re-dump the autoloader, and re-run setup:upgrade.
Is this error specific to 2.4.8-p3?
No. The same shape of error has shipped on every 2.4.x release where Adobe touched DI for an EAV / Catalog repository. The recipe (wipe generated/ + caches, dump-autoload, re-run setup:upgrade) works on 2.4.6, 2.4.7, 2.4.8 patches and on Mage-OS releases.
Do I need to wipe var/cache and var/page_cache too?
Yes. Magento caches a serialized copy of the compiled DI configuration in var/cache (or in Redis if you have a cache backend configured). Wiping just generated/ while a stale config dump lives in the cache will produce the same error on the next request. If you use Redis for caching, also run bin/magento cache:flush.
Will composer dump-autoload break anything?
No. It rebuilds Composer’s classmap from vendor/ on disk. It is safe to run on any environment. If your deploy uses the optimized autoloader, finish with composer dump-autoload --optimize so production gets the classmap form.
What if I get a different EAV interface error after the wipe — like AttributeManagementInterface?
Same root cause, same recipe. If the error survives a clean wipe + setup:upgrade, an installed extension is still pointing a <preference> at a class that was removed. Grep app/code and vendor for the failing interface inside di.xml files and disable the offending module.
Should I run setup:di:compile before or after setup:upgrade?
After. setup:upgrade applies schema and data patches — some of which may register new types or virtual types. setup:di:compile reads the final type graph after that work is done. Run them in this order: setup:upgrade → setup:di:compile → setup:static-content:deploy → cache:flush.
Can I skip wiping generated/ if I am in developer mode?
You can try, but you will probably hit a related error on the next request. Developer mode regenerates classes lazily, which is fine while you work, but the stored DI metadata may still be stale until something forces a recompile. Wipe generated/ anyway — it costs you nothing and removes one whole category of confusing failures.
Does this fix risk losing data?
No. Nothing under generated/ or var/cache is canonical. generated/ is compiled output from vendor/ + app/code; the caches are derived state. Magento will rebuild both on the next upgrade and request. Your database and media directory are untouched.
Is this related to PHP 8.4 compatibility?
Not directly. PHP 8.4 introduces its own class of errors (deprecated implicit-nullable types in Magento’s own code). The “Cannot instantiate interface” error happens before PHP even reaches the constructor body — it is the ObjectManager failing the type lookup. That said, if you jumped to PHP 8.4 at the same time as 2.4.8-p3, you may hit both errors back to back; fix the DI one first, then re-run.