tailwindlabs/tailwindcss · error · Error
`@utility ${node.params}` defines an invalid utility name. A
Error message
`@utility ${node.params}` defines an invalid utility name. A functional utility must end in `-*`. What it means
Thrown from the fallback chain when `createCssUtility(node)` returns null and the params end with `*` but do not end with `-*`. Functional (dynamic) utilities must use the `-*` suffix to mark the dynamic slot, e.g. `@utility icon-*`. A trailing `*` without the dash (like `icon*` or `icon_bar*`) is rejected because it cannot be unambiguously split into a static prefix and a dynamic value.
Source
Thrown at packages/tailwindcss/src/index.ts:241
// Collect custom `@utility` at-rules
if (node.name === '@utility') {
if (ctx.parent !== null) {
throw new Error('`@utility` cannot be nested.')
}
if (node.nodes.length === 0) {
throw new Error(
`\`@utility ${node.params}\` is empty. Utilities should include at least one property.`,
)
}
let utility = createCssUtility(node)
if (utility === null) {
if (!node.params.endsWith('-*')) {
if (node.params.endsWith('*')) {
throw new Error(
`\`@utility ${node.params}\` defines an invalid utility name. A functional utility must end in \`-*\`.`,
)
} else if (node.params.includes('*')) {
throw new Error(
`\`@utility ${node.params}\` defines an invalid utility name. The dynamic portion marked by \`-*\` must appear once at the end.`,
)
}
}
throw new Error(
`\`@utility ${node.params}\` defines an invalid utility name. Utilities should be alphanumeric and start with a lowercase letter.`,
)
}
customUtilities.push(utility)
}
// Collect paths from `@source` at-rules
if (node.name === '@source') {
if (node.nodes.length > 0) {View on GitHub (pinned to 16e94cbf7f)
Solutions
- Use the `-*` suffix: rename `@utility icon*` to `@utility icon-*`.
- If you intended a static utility, remove the trailing `*` entirely (`@utility icon`).
- Verify the resulting name matches `/^[a-z][a-zA-Z0-9-]*-\*$/` for functional utilities.
Example fix
/* before */
@utility icon* {
background-image: url('/icons/icon.svg');
}
/* after */
@utility icon-* {
background-image: url('/icons/icon--value.svg');
} Defensive patterns
Strategy: validation
Validate before calling
// Mirror the library's functional-utility name checks.
const ENDS_STAR_NOT_DASH_STAR = /^[a-z][a-zA-Z0-9-]*\*$/ // ends with *, not -*
function validateUtilityName(name: string): string | null {
if (ENDS_STAR_NOT_DASH_STAR.test(name) && !name.endsWith('-*')) {
return `Functional utility '${name}' must end in -*`
}
return null
} Prevention
- Standardize on the `-*` suffix for all dynamic utilities.
- Add a unit test that asserts your utility names match `/^[a-z][a-zA-Z0-9-]*-\*$/`.
- During code review, flag any `@utility` name whose only wildcard is a bare trailing `*`.
When it happens
Trigger: Defining `@utility icon* { ... }` or any name ending in `*` where the character before the `*` is not `-`.
Common situations: Assuming any trailing `*` works as a wildcard; translating a naming scheme from another system (e.g. `icon*-${name}`) into Tailwind v4 syntax.
Related errors
- `@utility ${node.params}` defines an invalid utility name. T
- `@utility ${node.params}` defines an invalid utility name. U
- `@utility` cannot be nested.
- `@utility ${node.params}` is empty. Utilities should include
- `@custom-variant ${name}` defines an invalid variant name. V
AI-assisted analysis of tailwindlabs/tailwindcss@16e94cbf7f (2026-08-12).
Data as JSON: /api/errors/df81c95455d60785.
Report an issue: GitHub.