{"record":{"id":"c8efd914b251b6c2","repo":"tailwindlabs/tailwindcss","slug":"custom-variant-name-selectors-join","errorCode":null,"errorMessage":"`@custom-variant ${name} (${selectors.join(',')})` selector is invalid.","messagePattern":"`@custom-variant (.+?) \\((.+?)\\)` selector is invalid\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/tailwindcss/src/index.ts","lineNumber":377,"sourceCode":"      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\n        for (let selector of selectors) {\n          selector = selector.trim()\n\n          if (selector[0] === '@') {\n            atRuleParams.push(selector)\n          } else {\n            styleRuleSelectors.push(selector)\n          }\n        }\n\n        let usesAtScope = atRuleParams.some((param) => param.startsWith('@scope'))","sourceCodeStart":359,"sourceCodeEnd":395,"githubUrl":"https://github.com/tailwindlabs/tailwindcss/blob/16e94cbf7f965c5ad697e90e940b5e178efad67c/packages/tailwindcss/src/index.ts#L359-L395","documentation":"Thrown in selector-form when the parenthesized selector, after stripping the outer parens and splitting on `,`, is empty or contains empty segments. The check `selectors.length === 0 || selectors.some(s => s.trim() === '')` rejects inputs like `()` or `(,)` that would produce no real selectors.","triggerScenarios":"Writing `@custom-variant hocus ()` or `@custom-variant hocus (,)` or `@custom-variant hocus ( ,  )`.","commonSituations":"Leaving the parens empty while editing; trailing comma from a deleted selector; whitespace-only entries.","solutions":["Provide at least one non-empty selector: `@custom-variant hocus (&:hover, &:focus)`.","Remove stray commas or whitespace inside the parens.","Switch to the body form if the variant logic is more complex than a selector list."],"exampleFix":"/* before */\n@custom-variant hocus (,);\n\n/* after */\n@custom-variant hocus (&:hover, &:focus);","handlingStrategy":"validation","validationCode":"// Validate the selector list inside @custom-variant name (...).\nfunction validateVariantSelectorList(selectorGroup: string): string | null {\n  // selectorGroup is the parenthesized portion, e.g. \"(&:hover, &:focus)\"\n  if (!selectorGroup.startsWith('(') || !selectorGroup.endsWith(')')) {\n    return null // not selector-form; body validation handles it\n  }\n  const inner = selectorGroup.slice(1, -1)\n  const parts = inner.split(',')\n  if (parts.length === 0 || parts.some((s) => s.trim() === '')) {\n    return `Selector list '${selectorGroup}' is empty or contains empty entries`\n  }\n  return null\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always put at least one real selector inside the parens.","When deleting a selector from a list, also remove its trailing comma.","Add a unit test that asserts your variant selector lists have no empty segments."],"tags":["at-custom-variant","selector","validation"],"backgroundTag":null,"analyzedSha":"16e94cbf7f965c5ad697e90e940b5e178efad67c","analyzedAt":"2026-08-12T06:02:42.469Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}