{"record":{"id":"20433aef5ac26faf","repo":"tailwindlabs/tailwindcss","slug":"custom-variant-cannot-be-nested","errorCode":null,"errorMessage":"`@custom-variant` cannot be nested.","messagePattern":"`@custom-variant` cannot be nested\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/tailwindcss/src/index.ts","lineNumber":354,"sourceCode":"\n          // No `@slot` found, so this is still a regular `@variant` at-rule\n          if (node.name === '@variant') {\n            variantNodes.push(node)\n          }\n        }\n      }\n\n      // Collect all the `@variant` at-rules, we will replace them later once\n      // all variants are registered in the system.\n      else {\n        variantNodes.push(node)\n      }\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.`)","sourceCodeStart":336,"sourceCodeEnd":372,"githubUrl":"https://github.com/tailwindlabs/tailwindcss/blob/16e94cbf7f965c5ad697e90e940b5e178efad67c/packages/tailwindcss/src/index.ts#L336-L372","documentation":"Thrown when a `@custom-variant` at-rule is encountered with a non-null parent (`ctx.parent !== null`). Custom variants must be defined at the stylesheet's top level so they can be registered globally before any `@variant` references are resolved.","triggerScenarios":"Placing `@custom-variant hocus (&:hover, &:focus)` inside `@media`, a selector, or any other rule.","commonSituations":"Trying to scope a variant to a subtree; refactors that indent directive blocks; copy-paste into an existing nested context.","solutions":["Move the `@custom-variant` rule to the top level of the stylesheet.","If you need conditional variant behavior, apply variants compositionally at the call site instead of nesting the definition.","Define the variant in your main CSS entry file rather than inside component-scoped CSS."],"exampleFix":"/* before */\n@media (prefers-color-scheme: dark) {\n  @custom-variant dark (&:where(.dark *));\n}\n\n/* after */\n@custom-variant dark (&:where(.dark *));\n/* then use: <div class=\"dark:bg-black\"> */","handlingStrategy":"validation","validationCode":"// Reject nested @custom-variant.\nimport postcss from 'postcss'\n\nfunction validateCustomVariantTopLevel(css: string): string[] {\n  const errors: string[] = []\n  postcss.parse(css).walkAtRules('@custom-variant', (rule) => {\n    if (rule.parent && rule.parent.type !== 'root') {\n      errors.push(`@custom-variant ${rule.params} must be at the top level`)\n    }\n  })\n  return errors\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Define all `@custom-variant` rules once in your CSS entry file at the top level.","Apply variants compositionally at the utility call site rather than nesting definitions.","Lint for non-root parents of `@custom-variant`."],"tags":["at-custom-variant","nesting","structure"],"backgroundTag":null,"analyzedSha":"16e94cbf7f965c5ad697e90e940b5e178efad67c","analyzedAt":"2026-08-12T06:02:42.469Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}