{"record":{"id":"9241d8e1858b6c1d","repo":"tailwindlabs/tailwindcss","slug":"custom-variant-name-cannot-have-both-a-selec","errorCode":null,"errorMessage":"`@custom-variant ${name}` cannot have both a selector and a body.","messagePattern":"`@custom-variant (.+?)` cannot have both a selector and a body\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/tailwindcss/src/index.ts","lineNumber":366,"sourceCode":"      }\n    }\n\n    // Register custom variants from `@custom-variant` at-rules\n    if (node.name === '@custom-variant') {\n      if (ctx.parent !== null) {\n        throw new Error('`@custom-variant` cannot be nested.')\n      }\n\n      let [name, selector] = segment(node.params, ' ')\n\n      if (!IS_VALID_VARIANT_NAME.test(name)) {\n        throw new Error(\n          `\\`@custom-variant ${name}\\` defines an invalid variant name. Variants should only contain alphanumeric, dashes, or underscore characters and start with a lowercase letter or number.`,\n        )\n      }\n\n      if (node.nodes.length > 0 && selector) {\n        throw new Error(`\\`@custom-variant ${name}\\` cannot have both a selector and a body.`)\n      }\n\n      // Variants with a selector, but without a body, e.g.: `@custom-variant hocus (&:hover, &:focus);`\n      if (node.nodes.length === 0) {\n        if (!selector) {\n          throw new Error(`\\`@custom-variant ${name}\\` has no selector or body.`)\n        }\n\n        let selectors = segment(selector.slice(1, -1), ',')\n        if (selectors.length === 0 || selectors.some((selector) => selector.trim() === '')) {\n          throw new Error(\n            `\\`@custom-variant ${name} (${selectors.join(',')})\\` selector is invalid.`,\n          )\n        }\n\n        let atRuleParams: string[] = []\n        let styleRuleSelectors: string[] = []\n","sourceCodeStart":348,"sourceCodeEnd":384,"githubUrl":"https://github.com/tailwindlabs/tailwindcss/blob/16e94cbf7f965c5ad697e90e940b5e178efad67c/packages/tailwindcss/src/index.ts#L348-L384","documentation":"Thrown when a `@custom-variant` provides both a parenthesized selector in its prelude AND a curly-brace body. Tailwind treats the variant definition as either selector-form (`@custom-variant hocus (&:hover, &:focus);`) or body-form (`@custom-variant hocus { ... }`), not both.","triggerScenarios":"Writing `@custom-variant hocus (&:hover, &:focus) { color: red; }` — selector in prelude and a non-empty body.","commonSituations":"Adding a body while forgetting to remove the selector argument; misunderstanding the two syntactic forms.","solutions":["Use only the selector form: `@custom-variant hocus (&:hover, &:focus);` (no body).","Or use only the body form: `@custom-variant hocus { &:hover, &:focus { @variant ...; } }` (no selector in prelude).","Pick the form that matches your intent: selector-form for simple selector composition, body-form for referencing other variants via `@variant`."],"exampleFix":"/* before */\n@custom-variant hocus (&:hover, &:focus) {\n  /* rules */\n}\n\n/* after — selector form */\n@custom-variant hocus (&:hover, &:focus);","handlingStrategy":"validation","validationCode":"// Ensure @custom-variant has at most one of (selector, body).\nimport postcss from 'postcss'\n\nfunction validateCustomVariantForm(css: string): string[] {\n  const errors: string[] = []\n  postcss.parse(css).walkAtRules('@custom-variant', (rule) => {\n    const hasBody = rule.nodes.length > 0\n    const hasSelector = rule.params.split(' ').length > 1\n    if (hasBody && hasSelector) {\n      errors.push(`@custom-variant ${rule.params} has both selector and body`)\n    }\n  })\n  return errors\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Pick one form per variant: selector-form (`name (...)`) or body-form (`name { ... }`).","In code review, flag any `@custom-variant` line that has both a `(...)` prelude and a `{ ... }` block.","Document the two forms in your project's CSS conventions."],"tags":["at-custom-variant","structure","validation"],"backgroundTag":null,"analyzedSha":"16e94cbf7f965c5ad697e90e940b5e178efad67c","analyzedAt":"2026-08-12T06:02:42.469Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}