Repository navigation
compile().warnings() is unreachable from a real build: 50 addWarning call sites, no Metro consumer #424
Description
The compiler records warnings that nothing in a real build reads
StylesheetBuilder.addWarning accumulates three channels — properties, values, functions — reachable through compile(css).warnings(). In src/compiler/declarations.ts there are 47 addWarning("value", …) call sites feeding the values channel, plus 3 addWarning("property", …).
None of them reach anybody running expo start.
$ grep -rn "\.warnings()" src --include=*.ts --include=*.tsx | grep -v __tests__
src/compiler/compiler.ts:202: warnings: () => builder.getWarnings(),
src/jest/index.ts:46: warnings: compiled.warnings(),compiler.ts:202 is the definition. src/jest/index.ts:46 is the only consumer, and it is behind a flag:
const debugDefault = Boolean(
process.env.REACT_NATIVE_CSS_TEST_DEBUG &&
typeof process.env.NODE_OPTIONS === "string" &&
process.env.NODE_OPTIONS.includes("--inspect"),
);src/metro/metro-transformer.ts — the path every real build takes — calls .stylesheet() and nothing else:
const productionJS = compile(css, {
...config.reactNativeCSS,
filename: filePath,
projectRoot: projectRoot,
}).stylesheet();So the observable behaviour of an unsupported declaration is: nothing happens, silently. The compiler knew, wrote it down, and threw the note away.
Why it matters
The values channel is where "this value has no React Native equivalent" is recorded. That is exactly the class of problem a developer cannot diagnose from the outside — the class name is present, the rule compiled, and one declaration quietly did nothing. A build-time log line is the difference between a five-minute fix and an afternoon.
Reproduction
import { compile } from "react-native-css/compiler";
console.log(compile(`.a { float: left; }`).warnings());
// { properties: [ 'float' ] }Run the same CSS through Metro and nothing is printed; the file transforms successfully.
Not a regression, and not new
This is how the channel has always worked — I am not reporting a break. I hit it while adding a warning for a new drop in #411 and found the new entries were as unreachable as the existing 47.
Possible shapes
metro-transformer.tscalls.warnings()after.stylesheet()and logs a summary through Metro's reporter.- The same, off by default behind a
reactNativeCSSoption, so an existing project does not suddenly gain a wall of output. - Nothing, if the channel is meant only as a compiler API for tooling — in which case it is worth saying so, because the call sites read as user-facing diagnostics.
Happy to do (1) or (2) if you have a preference. I did not fold it into #411 because it is orthogonal to that fix and predates it.
Activity
github-actions commentedon Aug 15, 2026
🤖 Auto-triage
Status: CONFIRMED
Type: feature
Version: v5
Findings
Verified the claim end-to-end.
compile().warnings()is defined atsrc/compiler/compiler.ts:202and the only non-test consumer issrc/jest/index.ts:46, which is gated behindREACT_NATIVE_CSS_TEST_DEBUG+--inspect.src/metro/metro-transformer.ts:39-43calls.stylesheet()and never touches.warnings(), so the 50addWarning(...)call sites insrc/compiler/declarations.ts(47"value"+ 3"property") never surface in a real build. Treated as an enhancement — no functional output is wrong, but a build-time diagnostic channel is going nowhere.What I tested
gh issue view 424— read the reportrgforaddWarning|\.warnings\(\)|getWarningsacrosssrc/— confirmed the 50 producer sites and the single gated consumersrc/metro/metro-transformer.ts— confirmed only.stylesheet()is called on the compile resultsrc/compiler/compiler.ts:202andsrc/compiler/stylesheet.ts:200-230— confirmed the API shapeNext steps
reactNativeCSSconfig, (3) declare the channel tooling-only. Reporter has offered to PR option 1 or 2.This is an automated triage. See auto-triage.yml.
YevheniiKotyrlo commentedon Aug 15, 2026
Opened #430 for this.
I went with option 1 plus option 2's escape hatch — on by default, one capped block per stylesheet,
warnings: "none"to silence — on the reasoning that an opt-in flag leaves the channel unreachable for everyone who does not read the docs, which is what the issue is about. If you would rather it defaulted to"none", that is a one-word change and I will make it.The two questions your triage raised are both answered in the PR with a measurement rather than a preference:
src/__tests__/vendor/tailwind) has 387 of its 759 cases asserting a warning, over 87 distinct properties, so a summary caps at ten entries per channel and counts the rest. A block is also keyed by file and by the message it would print, so it appears when a file's warnings change rather than on every save — otherwise a Tailwind rebuild would reprint it on every keystroke.Native only, and web carries no path rather than being skipped: the transformer returns to the stock Expo transformer before the compiler is reached, so a web bundle produces no warnings at all. There is a test asserting exactly that, including that the CSS was still processed whole.