{"record":{"id":"172e82ccdcf70445","repo":"tailwindlabs/tailwindcss","slug":"unsupported-content-value-pattern","errorCode":null,"errorMessage":"Unsupported content value: ${pattern}","messagePattern":"Unsupported content value: (.+?)","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"packages/@tailwindcss-upgrade/src/codemods/config/migrate-js-config.ts","lineNumber":368,"sourceCode":"    if (!unresolvedConfig.content) return false\n    if (Array.isArray(unresolvedConfig.content)) return false\n    if (unresolvedConfig.content.relative) return true\n    if (unresolvedConfig.future === 'all') return false\n    return unresolvedConfig.future?.relativeContentPathsByDefault ?? false\n  })()\n\n  let sourceGlobs = Array.isArray(unresolvedConfig.content)\n    ? unresolvedConfig.content.map((pattern) => ({ base, pattern }))\n    : (unresolvedConfig.content?.files ?? []).map((pattern) => {\n        if (typeof pattern === 'string' && contentIsRelative) {\n          return { base: path.dirname(configPath), pattern: pattern }\n        }\n        return { base, pattern }\n      })\n\n  for (let { base, pattern } of sourceGlobs) {\n    if (typeof pattern !== 'string') {\n      throw new Error('Unsupported content value: ' + pattern)\n    }\n\n    let sourceFiles = patternSourceFiles({\n      base,\n      pattern: pattern[0] === '!' ? pattern.slice(1) : pattern,\n      negated: pattern[0] === '!',\n    })\n\n    let autoContentContainsAllSourceFiles = true\n    for (let sourceFile of sourceFiles) {\n      if (!autoContentFiles.includes(sourceFile)) {\n        autoContentContainsAllSourceFiles = false\n        break\n      }\n    }\n\n    if (!autoContentContainsAllSourceFiles) {\n      sources.push({ base, pattern })","sourceCodeStart":350,"sourceCodeEnd":386,"githubUrl":"https://github.com/tailwindlabs/tailwindcss/blob/16e94cbf7f965c5ad697e90e940b5e178efad67c/packages/@tailwindcss-upgrade/src/codemods/config/migrate-js-config.ts#L350-L386","documentation":"The upgrade codemod that migrates a v3 JS config reads the legacy `content` field and maps each entry to a `{ base, pattern }` source glob. Every pattern must be a string; if a `content.files` entry is an object, number, or array element, the codemod cannot turn it into a glob and throws. This guards against malformed v3 configs that happened to be tolerated by v3's looser runtime.","triggerScenarios":"A `tailwind.config.js` whose `content` is `{ files: [ { raw: '…' }, './src/**' ] }` (object entries), or `content: ['./x', 42]`. The `typeof pattern !== 'string'` guard at migrate-js-config.ts:368 throws and concatenates the non-string value.","commonSituations":"Legacy configs using the undocumented `content.files[].raw` object form, or configs programmatically pushing non-string values into `content`.","solutions":["Edit the v3 config so every `content` / `content.files` entry is a plain string glob before running the upgrade.","Replace `raw` object entries with an actual file the glob can point at.","Re-run `npx @tailwindcss/upgrade` after fixing the config."],"exampleFix":"// before (v3 config)\nmodule.exports = { content: { files: [{ raw: '<div class=\"p-4\">' }] } }\n\n// after\nmodule.exports = { content: ['./src/**/*.html'] }","handlingStrategy":"validation","validationCode":"function assertContentStrings(content: unknown): string[] {\n  const files = Array.isArray(content) ? content : (content as any)?.files ?? []\n  for (const f of files) {\n    if (typeof f !== 'string') {\n      throw new Error(`Unsupported content entry (must be string): ${JSON.stringify(f)}`)\n    }\n  }\n  return files as string[]\n}","typeGuard":"function isStringContentArray(v: unknown): v is string[] {\n  return Array.isArray(v) && v.every(x => typeof x === 'string')\n}","tryCatchPattern":null,"preventionTips":["Keep content/content.files entries as plain string globs.","Avoid the legacy { raw: '...' } object form; extract to a real file.","Sanitize programmatically-built content arrays before upgrade."],"tags":["upgrade","config-migration","content-config"],"backgroundTag":null,"analyzedSha":"16e94cbf7f965c5ad697e90e940b5e178efad67c","analyzedAt":"2026-08-12T06:02:42.469Z","schemaVersion":2},"datasetVersion":"2026-08-12T13:17:24.610Z"}