{"record":{"id":"78a65df614b778c6","repo":"tailwindlabs/tailwindcss","slug":"source-cannot-have-a-body","errorCode":null,"errorMessage":"`@source` cannot have a body.","messagePattern":"`@source` cannot have a body\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/tailwindcss/src/index.ts","lineNumber":260,"sourceCode":"          } 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) {\n        throw new Error('`@source` cannot have a body.')\n      }\n\n      if (ctx.parent !== null) {\n        throw new Error('`@source` cannot be nested.')\n      }\n\n      let not = false\n      let inline = false\n      let path = node.params\n\n      if (path[0] === 'n' && path.startsWith('not ')) {\n        not = true\n        path = path.slice(4)\n      }\n\n      if (path[0] === 'i' && path.startsWith('inline(')) {\n        inline = true\n        path = path.slice(7, -1).trim()","sourceCodeStart":242,"sourceCodeEnd":278,"githubUrl":"https://github.com/tailwindlabs/tailwindcss/blob/16e94cbf7f965c5ad697e90e940b5e178efad67c/packages/tailwindcss/src/index.ts#L242-L278","documentation":"Thrown when an `@source` at-rule has any child nodes (`node.nodes.length > 0`). `@source` is a statement-style at-rule that takes its arguments in the prelude (`@source \"./**/*.html\"`); giving it a curly-brace body is structurally invalid and is rejected before the path is even inspected.","triggerScenarios":"Writing `@source \"./src/**/*.html\" { color: red; }` or any `@source ... { ... }` with a body block.","commonSituations":"Confusing `@source` (file globs for candidate scanning) with `@utility`/`@variant` (which have bodies); editor auto-completing a `{ }` block after the at-rule.","solutions":["Remove the body block — keep `@source` as a single statement ending with `;`.","If you meant to define a custom utility, use `@utility name { ... }` instead.","If you meant to register a custom variant with a body, use `@custom-variant name { ... }`."],"exampleFix":"/* before */\n@source \"./src/**/*.html\" {\n  /* ... */\n}\n\n/* after */\n@source \"./src/**/*.html\";","handlingStrategy":"validation","validationCode":"// Fail any @source that carries a body.\nimport postcss from 'postcss'\n\nfunction validateSourceHasNoBody(css: string): string[] {\n  const errors: string[] = []\n  postcss.parse(css).walkAtRules('@source', (rule) => {\n    if (rule.nodes.length > 0) {\n      errors.push(`@source ${rule.params} must not have a body`)\n    }\n  })\n  return errors\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Remember `@source` is a statement, not a block — always terminate with `;`.","Add an editor snippet that inserts `@source \"...\";` without a body.","Lint for at-rules whose names are statement-only but contain nodes."],"tags":["at-source","structure","validation"],"backgroundTag":null,"analyzedSha":"16e94cbf7f965c5ad697e90e940b5e178efad67c","analyzedAt":"2026-08-12T06:02:42.469Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}