laravel/framework · error · ViteException
The font manifest [style.variables] must be an object keyed
Error message
The font manifest [style.variables] must be an object keyed by alias; the manifest was likely produced by an incompatible plugin version.
What it means
Companion check to error 286: the 'variables' field of a style entry must also be an array (alias-keyed object). If it is set but not an array, ViteException is thrown with the same plugin-version caveat. Both checks guard resolveFilteredStyleContent() before it iterates aliases.
Source
Thrown at src/Illuminate/Foundation/ViteFonts.php:107
* @param array{inline?: string, file?: string, familyStyles?: array<string, string>, variables?: array<string, string>} $style
* @param list<string> $aliases
* @return string
*
* @throws \Illuminate\Foundation\ViteException
*/
protected function resolveFilteredStyleContent(array $style, array $aliases)
{
$familyStyles = $style['familyStyles'] ?? [];
$variables = $style['variables'] ?? [];
if (! is_array($familyStyles)) {
throw new ViteException(
'The font manifest [style.familyStyles] must be an object keyed by alias; the manifest was likely produced by an incompatible plugin version.'
);
}
if (! is_array($variables)) {
throw new ViteException(
'The font manifest [style.variables] must be an object keyed by alias; the manifest was likely produced by an incompatible plugin version.'
);
}
$parts = [];
foreach ($aliases as $alias) {
if (isset($familyStyles[$alias])) {
$parts[] = $familyStyles[$alias];
}
}
if ($variables !== []) {
$parts[] = $this->filterVariables($variables, $aliases);
}
return implode("\n\n", $parts);
}View on GitHub (pinned to e0f6eb3518)
Solutions
- Match the font plugin version to the Laravel Vite integration version.
- Regenerate the manifest so variables is {"alias": "--var: value;"} shaped.
- Audit with jq '.styles[] | .variables | type' across the manifest.
- Filter the aliases list to only those the producer actually emits in the correct shape.
Example fix
// before
{ "style": { "variables": "--font-heading: Inter;" } }
// after
{ "style": { "variables": { "default": "--font-heading: Inter;" } } } Defensive patterns
Strategy: validation
Validate before calling
$manifest = json_decode(file_get_contents($path), true);
foreach ($manifest['styles'] ?? [] as $style) {
if (isset($style['variables']) && ! is_array($style['variables'])) {
throw new RuntimeException('variables must be an object; plugin version mismatch.');
}
} Type guard
function variablesWellShaped(array $style): bool {
return ! isset($style['variables']) || is_array($style['variables']);
} Try / catch
use Illuminate\Foundation\ViteException;
try {
$css = $viteFonts->resolveFilteredStyleContent($style, $aliases);
} catch (ViteException $e) {
if (str_contains($e->getMessage(), 'variables')) { /* rebuild manifest */ }
} Prevention
- Lock font plugin version to the Laravel integration version.
- Lint manifest in CI: assert variables is an object.
- Regenerate manifests after any upgrade.
- Document the alias-keyed object contract for any custom font plugin.
When it happens
Trigger: A font manifest style entry has 'variables' set to a non-array value (string, number, null-filled object). Same root cause as 286 — producer/consumer version skew on the manifest schema.
Common situations: Plugin upgrade/downgrade mismatch. Manually crafted manifests. Switching between CSS-variable-based font plugins and older ones.
Related errors
- The font manifest [style.familyStyles] must be an object key
- The font manifest at [{$path}] is not valid JSON.
- Unable to locate file in Vite manifest: {$file}.
- Callback must be a callable, callback array, or a 'Class@met
- Auth guard [{$name}] is not defined.
AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11).
Data as JSON: /api/errors/f1f0181e1b7df66c.
Report an issue: GitHub.