vercel/next.js · error

Axes can only be defined for variable fonts when the weight

Error message

Axes can only be defined for variable fonts when the weight property is nonexistent or set to `variable`.

What it means

Thrown by options_from_request() when `axes` is provided for a variable font but the resolved weights are not FontWeights::Variable — i.e. you set both explicit numeric weights and custom axes. Axes manipulate the variable axes of the font, which requires the weight axis itself to be in variable mode (weight absent or 'variable').

Source

Thrown at crates/next-core/src/next_font/google/options.rs:183

    if !ALLOWED_DISPLAY_VALUES.contains(&display.as_str()) {
        anyhow::bail!(
            "Invalid display value {} for font {}.\nAvailable display values: {}",
            display,
            font_family,
            ALLOWED_DISPLAY_VALUES.join(", ")
        )
    }

    if let Some(axes) = argument.axes.as_ref()
        && !axes.is_empty()
    {
        if !supports_variable_weight {
            anyhow::bail!("Axes can only be defined for variable fonts.")
        }

        if weights != FontWeights::Variable {
            anyhow::bail!(
                "Axes can only be defined for variable fonts when the weight property is \
                 nonexistent or set to `variable`."
            )
        }
    }

    Ok(NextFontGoogleOptions {
        font_family,
        weights,
        styles,
        display,
        preload: argument.preload.unwrap_or(true),
        selected_variable_axes: argument.axes,
        fallback: argument.fallback,
        adjust_font_fallback: argument.adjust_font_fallback.unwrap_or(true),
        variable: argument.variable,
        subsets: argument.subsets,
    })

View on GitHub (pinned to 0ae8c72462)

Solutions

  1. Remove the explicit `weight` (or set it to 'variable') so the font stays in variable mode, then keep `axes`.
  2. If you need a fixed weight, drop `axes` and rely on the chosen weight only.

Example fix

// before
const font = Inter({
  subsets: ['latin'],
  weight: '400',
  axes: [{ tag: 'opsz', min: 14, max: 32 }],
})
// after
const font = Inter({
  subsets: ['latin'],
  weight: 'variable',
  axes: [{ tag: 'opsz', min: 14, max: 32 }],
})
Defensive patterns

Strategy: validation

Prevention

When it happens

Trigger: Passing `weight: '400'` (or any fixed weight) together with an `axes` array to a variable font. The validator allows axes only when weights == FontWeights::Variable.

Common situations: Wanting a specific weight plus a custom optical-size axis; misunderstanding that fixing the weight disables the variable axis system.

Related errors


AI-assisted analysis of vercel/next.js@0ae8c72462 (2026-08-06). Data as JSON: /api/errors/750e3ae4dd887c3f. Report an issue: GitHub.