MissingViewData
Emitted when a Blade template declares a variable that the call site rendering it never passes. The variable is undefined at render time, and Laravel’s HandleExceptions turns the warning into an ErrorException in every environment, so `` fails instead of printing nothing.
A template declares variables with a @var docblock or a @props entry. Every declared variable is required, including T|null and mixed; a declaration ending in = null is optional. See Declaring view variables.
Example
```blade<?php /** @var string $name */ ?>
```php
view('profile', []); // MissingViewData
view('profile', ['name' => 'Ada']); // OK
view('profile', [])->with('name', 'Ada'); // OK: the whole with() chain is read at once
In a template, @includeIsolated('profile', [...]) is checked the same way, and so is @includeIsolated('profile'), which passes no data. An ordinary @include never reports a missing variable, because the included template also inherits the including one’s scope.
How to fix
- Pass the declared variable at the call site.
- Declare it optional if it genuinely is: give it a default in the template’s
@props([...]), or end the declaration with= null(@var string|null $subtitle = null). - Drop the declaration if the template no longer reads that variable.
Limitations
The check declines rather than guess. On top of the shared supported call sites (literal view name, analyzed template, recognized chain), it is silent when:
- The template declares nothing, or its
@props([...])array is not fully literal (the declared set is then only a lower bound). - The
@propsentry carries a literal default, which Blade fills in itself, or the@vardeclaration ends in= null. - The name is one the framework supplies to every view (
$app,$errors, anything a providershare()d at boot): it is never a declaration. - The variable is supplied by a view composer or creator. The other declared variables of that view are still checked, but when a composer cannot be read, the whole view is skipped. See Composers and creators.
- The call site is the
render()method of anIlluminate\View\Componentsubclass:render()is public and a caller can chain->with([...])on its result. Its framework-supplied properties still take part in InvalidViewData. See Framework-supplied data, which also lists the Mailable, MailMessage and Livewire receivers with an open key set. - The call site is in a named function or a
private/protectedmethod (static and trait methods included), returned or not: its caller can complete the view, as in$this->greetingView()->with('name', $name). A trait method counts with the visibility its using classes give it (use T { helper as public; }keeps it checked). InvalidViewData and UnusedViewData still run there. Public methods and closures (a closure inside a private helper included) are still checked. Residuals: a private helper that is itself the rendering end is not checked for missing keys, and apublichelper whose callers complete the view still reports. - The supplied key set cannot be proven closed: a spread in the data array, a dynamic
with()key, a$mergeDataargument, or a data argument whose type is not a single sealed keyed array.
Known false positive: variables bound outside the call site
A variable can reach a view without the call site passing it: a composer or creator registered after boot, or @inject('metrics', 'App\Services\Metrics') inside the template. It is declared by the template but never passed, so it is reported. Drop its @var declaration, or suppress the issue at the affected statement:
/** @psalm-suppress MissingViewData */
return view('profile', []);
For application-wide suppression and promotion, see the shared reporting level.