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

  1. Match the font plugin version to the Laravel Vite integration version.
  2. Regenerate the manifest so variables is {"alias": "--var: value;"} shaped.
  3. Audit with jq '.styles[] | .variables | type' across the manifest.
  4. 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

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


AI-assisted analysis of laravel/framework@e0f6eb3518 (2026-08-11). Data as JSON: /api/errors/f1f0181e1b7df66c. Report an issue: GitHub.