Summary
Scanning a source file containing the substring row-constructor (even inside a code comment) crashes Tailwind's compile step with a minified TypeError: X.map is not a function. Root cause appears to be a prototype-pollution-style lookup on a plain-object staticValues map inside the row-* utility's
compile function.
Environment
tailwindcss: 4.1.18
@tailwindcss/cli: 4.1.18
- Node:
v25.2.1
- OS: macOS (Darwin arm64)
Minimal Reproduction
mkdir tw-repro && cd tw-repro
npm init -y
npm i -D tailwindcss@4.1.18 @tailwindcss/cli@4.1.18
printf '@import "tailwindcss";\n' > input.css
printf 'const x = "row-constructor";\n' > candidate.ts
npx @tailwindcss/cli -i input.css -o output.css
Expected
Compile succeeds. row-constructor is not a valid row-* utility value and should be ignored (same as row-notathing, which works fine).
Actual
≈ tailwindcss v4.1.18
TypeError: V.map is not a function
Full stack from a Turbopack dev run on the same source:
TypeError: E.map is not a function
at Object.compileFn (.../tailwindcss/dist/lib.js:10:20844)
at Ca (.../tailwindcss/dist/lib.js:16:38197)
at Li (.../tailwindcss/dist/lib.js:16:37080)
at U.factory (.../tailwindcss/dist/lib.js:16:28513)
at U.get (.../tailwindcss/dist/lib.js:1:8654)
at Object.compileAstNodes (.../tailwindcss/dist/lib.js:16:29208)
at Te (.../tailwindcss/dist/lib.js:16:36451)
at Object.build (.../tailwindcss/dist/lib.js:38:1179)
at Object.Once (.../@tailwindcss/postcss/dist/index.js:10:5864)
Root Cause (hypothesis)
Inside the compile path for the row-* utility, a lookup like:
let E = g.staticValues[b.value.value];
if (E) return E.map(ee);
runs against staticValues held as a plain object (not Object.create(null)). When the candidate's value is constructor, the lookup falls through to
Object.prototype.constructor — the Object function — which is truthy but not an array, so .map() throws.
Scope / Other Affected Tokens
Confirmed crashing:
Confirmed not crashing (tested on the same setup, so the bug is utility-specific — probably only utilities whose static-values map is a plain object):
text-constructor, font-constructor, text-toString, text-hasOwnProperty, text-__proto__
Likely also affected: any row-<Object.prototype key> — e.g. row-toString, row-hasOwnProperty, row-valueOf.
Suggested Fix
Either:
- Construct the
staticValues map with Object.create(null), so inherited keys are not accessible; or
- Gate the lookup with
Object.hasOwn(g.staticValues, key) before reading.
Why this matters in practice
The candidate extractor scans any string in any source file, including comments. Our codebase crashed because of a SQL-flavored comment:
// grows switch to a row-constructor IN — e.g.
That's a plausible substring to appear naturally in prose or docs, and the failure mode is a minified X.map is not a function with no indication of
which candidate triggered it — hard to diagnose without bisecting source files.
Summary
Scanning a source file containing the substring
row-constructor(even inside a code comment) crashes Tailwind's compile step with a minifiedTypeError: X.map is not a function. Root cause appears to be a prototype-pollution-style lookup on a plain-objectstaticValuesmap inside therow-*utility'scompile function.
Environment
tailwindcss:4.1.18@tailwindcss/cli:4.1.18v25.2.1Minimal Reproduction
Expected
Compile succeeds.
row-constructoris not a validrow-*utility value and should be ignored (same asrow-notathing, which works fine).Actual
Full stack from a Turbopack dev run on the same source:
Root Cause (hypothesis)
Inside the compile path for the
row-*utility, a lookup like:runs against
staticValuesheld as a plain object (notObject.create(null)). When the candidate's value isconstructor, the lookup falls through toObject.prototype.constructor— theObjectfunction — which is truthy but not an array, so.map()throws.Scope / Other Affected Tokens
Confirmed crashing:
row-constructorConfirmed not crashing (tested on the same setup, so the bug is utility-specific — probably only utilities whose static-values map is a plain object):
text-constructor,font-constructor,text-toString,text-hasOwnProperty,text-__proto__Likely also affected: any
row-<Object.prototype key>— e.g.row-toString,row-hasOwnProperty,row-valueOf.Suggested Fix
Either:
staticValuesmap withObject.create(null), so inherited keys are not accessible; orObject.hasOwn(g.staticValues, key)before reading.Why this matters in practice
The candidate extractor scans any string in any source file, including comments. Our codebase crashed because of a SQL-flavored comment:
// grows switch to a row-constructor IN — e.g.That's a plausible substring to appear naturally in prose or docs, and the failure mode is a minified
X.map is not a functionwith no indication ofwhich candidate triggered it — hard to diagnose without bisecting source files.