Show more specific error for functional-like but invalid utility names (#18568)

Fixes #18566

The behavior is by design but the error message could definitely be
improved.
This commit is contained in:
Jordan Pittman 2025-07-18 12:31:19 -04:00 committed by GitHub
parent 298ad08653
commit 939fda6f4e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 37 additions and 0 deletions

View File

@ -17,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Ignore consecutive semicolons in the CSS parser ([#18532](https://github.com/tailwindlabs/tailwindcss/pull/18532))
- Center the dropdown icon added to an input with a paired datalist ([#18511](https://github.com/tailwindlabs/tailwindcss/pull/18511))
- Extract candidates in Slang templates ([#18565](https://github.com/tailwindlabs/tailwindcss/pull/18565))
- Improve error messages when encountering invalid functional utility names ([#18568](https://github.com/tailwindlabs/tailwindcss/pull/18568))
## [4.1.11] - 2025-06-26

View File

@ -4354,6 +4354,30 @@ describe('@utility', () => {
`[Error: \`@utility 💨\` defines an invalid utility name. Utilities should be alphanumeric and start with a lowercase letter.]`,
)
})
test('A functional @utility must end in -*', () => {
return expect(
compileCss(css`
@utility foo* {
color: red;
}
`),
).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: \`@utility foo*\` defines an invalid utility name. A functional utility must end in \`-*\`.]`,
)
})
test('Only the last part of a functional @utility can be dynamic', () => {
return expect(
compileCss(css`
@utility my-*-utility {
color: red;
}
`),
).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: \`@utility my-*-utility\` defines an invalid utility name. The dynamic portion marked by \`-*\` must appear once at the end.]`,
)
})
})
test('addBase', async () => {

View File

@ -229,6 +229,18 @@ async function parseCss(
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.`,
)