All container exceptions live in the InitPHP\Container\Exception namespace and implement a PSR-11 interface, so you can also catch them by the standard Psr\Container\ContainerExceptionInterface / NotFoundExceptionInterface contracts.
Psr\Container\ContainerExceptionInterface
└── InitPHP\Container\Exception\ContainerException
├── NotFoundException (also implements NotFoundExceptionInterface)
├── DependencyIsNotInstantiableException
├── DependencyHasNoDefaultValueException
└── CircularDependencyException
ContainerException is the common base, so a single catch handles every container error:
use InitPHP\Container\Exception\ContainerException;
try {
$service = $container->get(App\Service::class);
} catch (ContainerException $e) {
// any container failure
}To distinguish a missing entry specifically, catch NotFoundException (or the PSR interface) first.
Thrown by get() when the identifier is neither a registered entry nor an existing class name. Implements Psr\Container\NotFoundExceptionInterface.
use InitPHP\Container\Exception\NotFoundException;
try {
$container->get('does-not-exist');
} catch (NotFoundException $e) {
echo $e->getMessage(); // No entry was found for identifier "does-not-exist".
}This is also thrown when you request an unbound interface directly, because class_exists() does not report interfaces:
interface PaymentGatewayInterface
{
}
$container->get(PaymentGatewayInterface::class); // NotFoundExceptionThrown when the container reaches a class it cannot instantiate: an abstract class or a class with a non-public constructor.
use InitPHP\Container\Exception\DependencyIsNotInstantiableException;
abstract class AbstractRepository
{
}
try {
$container->get(AbstractRepository::class);
} catch (DependencyIsNotInstantiableException $e) {
echo $e->getMessage(); // Class "AbstractRepository" is not instantiable.
}Thrown when a constructor parameter cannot be autowired and has neither a default value nor a nullable type to fall back on. Typical cases: a scalar without a default, or an unbound interface dependency.
use InitPHP\Container\Exception\DependencyHasNoDefaultValueException;
class Connection
{
public function __construct(public string $dsn)
{
}
}
try {
$container->get(Connection::class);
} catch (DependencyHasNoDefaultValueException $e) {
echo $e->getMessage(); // Unable to resolve the value of parameter "$dsn".
}The fix is to give the container what it needs — register the value, provide a default, or bind the interface:
$container->set('connection', fn () => new Connection('sqlite::memory:'));Thrown when a class depends on itself, directly or through a chain, which would otherwise cause unbounded recursion.
use InitPHP\Container\Exception\CircularDependencyException;
class A
{
public function __construct(public B $b)
{
}
}
class B
{
public function __construct(public A $a)
{
}
}
try {
$container->get(A::class);
} catch (CircularDependencyException $e) {
echo $e->getMessage(); // Circular dependency detected while resolving "...".
}Break the cycle by introducing an interface and a factory, or by injecting one of the classes lazily after construction.
Because the exceptions implement the PSR-11 interfaces, code that depends only on psr/container can catch them without referencing InitPHP types:
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;
try {
$container->get($id);
} catch (NotFoundExceptionInterface $e) {
// unknown identifier
} catch (ContainerExceptionInterface $e) {
// any other resolution error
}