{"record":{"id":"df81c95455d60785","repo":"tailwindlabs/tailwindcss","slug":"utility-node-params-defines-an-invalid-utili","errorCode":null,"errorMessage":"`@utility ${node.params}` defines an invalid utility name. A functional utility must end in `-*`.","messagePattern":"`@utility (.+?)` defines an invalid utility name\\. A functional utility must end in `-\\*`\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/tailwindcss/src/index.ts","lineNumber":241,"sourceCode":"    // Collect custom `@utility` at-rules\n    if (node.name === '@utility') {\n      if (ctx.parent !== null) {\n        throw new Error('`@utility` cannot be nested.')\n      }\n\n      if (node.nodes.length === 0) {\n        throw new Error(\n          `\\`@utility ${node.params}\\` is empty. Utilities should include at least one property.`,\n        )\n      }\n\n      let utility = createCssUtility(node)\n      if (utility === null) {\n        if (!node.params.endsWith('-*')) {\n          if (node.params.endsWith('*')) {\n            throw new Error(\n              `\\`@utility ${node.params}\\` defines an invalid utility name. A functional utility must end in \\`-*\\`.`,\n            )\n          } else if (node.params.includes('*')) {\n            throw new Error(\n              `\\`@utility ${node.params}\\` defines an invalid utility name. The dynamic portion marked by \\`-*\\` must appear once at the end.`,\n            )\n          }\n        }\n\n        throw new Error(\n          `\\`@utility ${node.params}\\` defines an invalid utility name. Utilities should be alphanumeric and start with a lowercase letter.`,\n        )\n      }\n\n      customUtilities.push(utility)\n    }\n\n    // Collect paths from `@source` at-rules\n    if (node.name === '@source') {\n      if (node.nodes.length > 0) {","sourceCodeStart":223,"sourceCodeEnd":259,"githubUrl":"https://github.com/tailwindlabs/tailwindcss/blob/16e94cbf7f965c5ad697e90e940b5e178efad67c/packages/tailwindcss/src/index.ts#L223-L259","documentation":"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.","triggerScenarios":"Defining `@utility icon* { ... }` or any name ending in `*` where the character before the `*` is not `-`.","commonSituations":"Assuming any trailing `*` works as a wildcard; translating a naming scheme from another system (e.g. `icon*-${name}`) into Tailwind v4 syntax.","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."],"exampleFix":"/* before */\n@utility icon* {\n  background-image: url('/icons/icon.svg');\n}\n\n/* after */\n@utility icon-* {\n  background-image: url('/icons/icon--value.svg');\n}","handlingStrategy":"validation","validationCode":"// Mirror the library's functional-utility name checks.\nconst ENDS_STAR_NOT_DASH_STAR = /^[a-z][a-zA-Z0-9-]*\\*$/ // ends with *, not -*\n\nfunction validateUtilityName(name: string): string | null {\n  if (ENDS_STAR_NOT_DASH_STAR.test(name) && !name.endsWith('-*')) {\n    return `Functional utility '${name}' must end in -*`\n  }\n  return null\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["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 `*`."],"tags":["at-utility","functional-utility","naming","wildcard"],"backgroundTag":null,"analyzedSha":"16e94cbf7f965c5ad697e90e940b5e178efad67c","analyzedAt":"2026-08-12T06:02:42.469Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}