laravel/framework · error · BindingResolutionException

Target [$concrete] is not instantiable while building [$prev

Error message

Target [$concrete] is not instantiable while building [$previous].

What it means

Thrown by Container::notInstantiable when the concrete being built (an interface, abstract class, or trait) is not instantiable AND the buildStack is non-empty — meaning the failure occurred while resolving a dependency of another class. The message lists the chain of classes currently being built so you can see which dep caused it.

Source

Thrown at src/Illuminate/Container/Container.php:1436

    /**
     * Throw an exception that the concrete is not instantiable.
     *
     * @param  string  $concrete
     * @return void
     *
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    protected function notInstantiable($concrete)
    {
        if (! empty($this->buildStack)) {
            $previous = implode(', ', $this->buildStack);

            $message = "Target [$concrete] is not instantiable while building [$previous].";
        } else {
            $message = "Target [$concrete] is not instantiable.";
        }

        throw new BindingResolutionException($message);
    }

    /**
     * Throw an exception for an unresolvable primitive.
     *
     * @return void
     *
     * @throws \Illuminate\Contracts\Container\BindingResolutionException
     */
    protected function unresolvablePrimitive(ReflectionParameter $parameter)
    {
        $message = "Unresolvable dependency resolving [$parameter] in class {$parameter->getDeclaringClass()->getName()}";

        throw new BindingResolutionException($message);
    }

    /**
     * Register a new before resolving callback for all types.

View on GitHub (pinned to bd6b5437e6)

Solutions

  1. Bind the interface to a concrete: $this->app->bind(Contract::class, Implementation::class).
  2. Inspect the 'while building [...]' list to find which dependent class pulls in the non-instantiable type and fix its binding.
  3. Use $this->app->bind(Contract::class, fn () => $mock) in tests to supply a fake.
  4. Make sure your ServiceProvider is registered in config/app.php (or discovered) so the binding runs.

Example fix

// before
// App\Contracts\Payment has no binding
app()->make(OrderProcessor::class);

// after
// in AppServiceProvider::register
$this->app->bind(\App\Contracts\Payment::class, \App\Services\StripePayment::class);
Defensive patterns

Strategy: validation

Validate before calling

$reflection = new \ReflectionClass($concrete);
if (! $reflection->isInstantiable() && ! app()->bound($concrete)) {
    throw new \LogicException("{$concrete} is not instantiable; bind it first");
}

Type guard

function isInstantiableOrBound(string $class, \Illuminate\Container\Container $c): bool
{
    if ($c->bound($class)) return true;
    return (new \ReflectionClass($class))->isInstantiable();
}

Try / catch

use Illuminate\Contracts\Container\BindingResolutionException;
try {
    app()->make($service);
} catch (BindingResolutionException $e) {
    if (str_contains($e->getMessage(), 'is not instantiable while building')) {
        // bind missing interface then retry
    }
    throw $e;
}

Prevention

When it happens

Trigger: Resolving class A whose constructor requires interface B that has no concrete binding: getConcrete returns B, build() reflects B, isInstantiable() is false, buildStack contains A → message 'Target [B] is not instantiable while building [A].'

Common situations: Forgetting to bind an interface to a concrete in a service provider; refactor replacing a class with an interface without updating bindings; scoped/singleton binding lost after clearing the container; testing without registering the test doubles in the container.

Related errors


AI-assisted analysis of laravel/framework@bd6b5437e6 (2026-08-06). Data as JSON: /data/errors/70bf8bd65bb869d7.json. Report an issue: GitHub.