tailwindlabs/tailwindcss · error · Error

Unexpected `@plugin` option: Value of declaration `${toCss([

Error message

Unexpected `@plugin` option: Value of declaration `${toCss([decl]).trim()}` is not supported.

Using an object as a plugin option is currently only supported in JavaScript configuration files.

What it means

Thrown when parsing a `@plugin` option declaration whose value starts with `{` and ends with `}` — i.e. an object literal. CSS `@plugin` options only support JSON primitives (null, bool, number, quoted string); object values require a JavaScript config file. The full declaration is echoed via `toCss([decl]).trim()`.

Source

Thrown at packages/tailwindcss/src/compat/apply-compat-hooks.ts:101

        let parts = segment(value, ',').map((part) => {
          part = part.trim()

          if (part === 'null') {
            return null
          } else if (part === 'true') {
            return true
          } else if (part === 'false') {
            return false
          } else if (!Number.isNaN(Number(part))) {
            return Number(part)
          } else if (
            (part[0] === '"' && part[part.length - 1] === '"') ||
            (part[0] === "'" && part[part.length - 1] === "'")
          ) {
            return part.slice(1, -1)
          } else if (part[0] === '{' && part[part.length - 1] === '}') {
            throw new Error(
              `Unexpected \`@plugin\` option: Value of declaration \`${toCss([decl]).trim()}\` is not supported.\n\nUsing an object as a plugin option is currently only supported in JavaScript configuration files.`,
            )
          }

          return part
        })

        options[decl.property] = parts.length === 1 ? parts[0] : parts
      }

      pluginPaths.push([
        {
          id: pluginPath,
          base: ctx.context.base as string,
          reference: !!ctx.context.reference,
          src: node.src,
        },
        Object.keys(options).length > 0 ? options : null,

View on GitHub (pinned to 16e94cbf7f)

Solutions

  1. Move that plugin's configuration into a JS/TS config file (`tailwind.config.js`) where object options are supported.
  2. Flatten the object into primitive declarations the plugin can read, if the plugin accepts that shape.
  3. Use `plugin.withOptions()` and pass options from JS instead of CSS `@plugin`.

Example fix

// before (CSS)
@plugin "./my-plugin.js" {
  theme: { primary: "#f00" };
}
// after (tailwind.config.js)
plugins: [require("./my-plugin.js")({ theme: { primary: "#f00" } })]
Defensive patterns

Strategy: validation

Validate before calling

function assertNoObjectOption(node) {
  for (const decl of node.nodes ?? []) {
    const v = (decl.value ?? '').trim();
    if (v[0] === '{' && v[v.length - 1] === '}') {
      throw new Error(`Object option ${decl.property} not supported in CSS @plugin; use JS config`);
    }
  }
}

Prevention

When it happens

Trigger: Writing `@plugin "x.js" { config: { key: value } }`. The part-wise parser hits the `{...}` branch and rejects it.

Common situations: Migrating a JS plugin config that uses nested option objects into CSS `@plugin` syntax; assuming CSS plugin options mirror the JS object shape.

Related errors


AI-assisted analysis of tailwindlabs/tailwindcss@16e94cbf7f (2026-08-12). Data as JSON: /api/errors/2d1a4819bc14cade. Report an issue: GitHub.