{"record":{"id":"f917a35b0f323e25","repo":"tailwindlabs/tailwindcss","slug":"could-not-find-the-tailwind-css-v3-prefix-config","errorCode":null,"errorMessage":"Could not find the Tailwind CSS v3 `prefix` configuration inside the JavaScript config.","messagePattern":"Could not find the Tailwind CSS v3 `prefix` configuration inside the JavaScript config\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@tailwindcss-upgrade/src/codemods/template/migrate-prefix.ts","lineNumber":74,"sourceCode":"    designSystem.theme.prefix = originalPrefix\n  }\n\n  if (!candidate) return rawCandidate\n\n  return designSystem.printCandidate(candidate)\n}\n\n// Parses a raw candidate with v3 compatible prefix syntax. This won't match if\n// the `base` part of the candidate does not match the configured prefix, unless\n// a bare candidate is used.\nfunction extractV3Base(\n  designSystem: DesignSystem,\n  userConfig: Config,\n  rawCandidate: string,\n): { base: string; start: number; end: number } | null {\n  if (!designSystem.theme.prefix) return null\n  if (!userConfig.prefix)\n    throw new Error(\n      'Could not find the Tailwind CSS v3 `prefix` configuration inside the JavaScript config.',\n    )\n\n  // hover:focus:underline\n  // ^^^^^ ^^^^^^           -> Variants\n  //             ^^^^^^^^^  -> Base\n  let rawVariants = segment(rawCandidate, ':')\n\n  // SAFETY: At this point it is safe to use TypeScript's non-null assertion\n  // operator because even if the `input` was an empty string, splitting an\n  // empty string by `:` will always result in an array with at least one\n  // element.\n  let base = rawVariants.pop()!\n  let start = rawCandidate.length - base.length\n  let end = start + base.length\n\n  let important = false\n  let negative = false","sourceCodeStart":56,"sourceCodeEnd":92,"githubUrl":"https://github.com/tailwindlabs/tailwindcss/blob/16e94cbf7f965c5ad697e90e940b5e178efad67c/packages/@tailwindcss-upgrade/src/codemods/template/migrate-prefix.ts#L56-L92","documentation":"`extractV3Base` parses a v3 candidate with prefix awareness. It first checks `designSystem.theme.prefix`; if a prefix is configured in the design system, it then requires the v3 JS config to also declare `userConfig.prefix`. If the config omits `prefix` while the design system has one, the migration cannot align the two prefix sources and throws.","triggerScenarios":"Running the upgrade with a design system built from a CSS `@theme` that defines a prefix, but the legacy `tailwind.config.js` has no `prefix` field (or it was deleted). migrate-prefix.ts:74 throws after the `designSystem.theme.prefix` truthiness check passes but `userConfig.prefix` is falsy.","commonSituations":"Partially migrated configs where the prefix was moved into `@theme` but the JS config was stripped, or inconsistent prefix configuration between CSS and JS during a manual migration attempt.","solutions":["Add the matching `prefix` field to the v3 JS config (e.g. `prefix: 'tw-'`) so it agrees with the design system's `@theme` prefix.","Or remove the prefix from `@theme` if no prefix is intended, then re-run the upgrade.","Ensure the prefix values are identical across both sources."],"exampleFix":"// before (config missing prefix while @theme has one)\nmodule.exports = { theme: { /* … */ } }\n\n// after\nmodule.exports = { prefix: 'tw-', theme: { /* … */ } }","handlingStrategy":"validation","validationCode":"function assertPrefixConsistency(designSystemPrefix: string | undefined, userConfigPrefix: string | undefined) {\n  if (designSystemPrefix && !userConfigPrefix) {\n    throw new Error('Design system has a prefix but the JS config omits prefix; add matching prefix:')\n  }\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Keep prefix declarations identical in @theme and the JS config during migration.","Don't strip the JS config prefix while a @theme prefix remains.","Re-run the upgrade after aligning both prefix sources."],"tags":["upgrade","prefix","config-migration"],"backgroundTag":null,"analyzedSha":"16e94cbf7f965c5ad697e90e940b5e178efad67c","analyzedAt":"2026-08-12T06:02:42.469Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}