Skip to content

Don't crash when theme.keyframes is explicitly set to null - #20425

Open
koreahghg wants to merge 2 commits into
tailwindlabs:mainfrom
koreahghg:fix/keyframes-null-theme-crash
Open

Don't crash when theme.keyframes is explicitly set to null#20425
koreahghg wants to merge 2 commits into
tailwindlabs:mainfrom
koreahghg:fix/keyframes-null-theme-crash

Conversation

@koreahghg

Copy link
Copy Markdown
Contributor

Summary

Setting theme.keyframes (or theme.extend.keyframes) to null in a JS config crashes the entire build.

keyframesToRules in packages/tailwindcss/src/compat/apply-keyframes-to-theme.ts checks 'keyframes' in resolvedConfig.theme before calling Object.entries(resolvedConfig.theme.keyframes). But resolveConfig (see packages/tailwindcss/src/compat/config/resolve-config.ts) resolves every theme value with value ?? null, so a theme key explicitly set to null — the documented way to clear a theme key, e.g. theme.extend.colors: null — still exists on the object via in, just with a null value. That means theme: { keyframes: null } reaches Object.entries(null), which throws TypeError: Cannot convert undefined or null to object and crashes the whole build.

Every sibling module that reads from the resolved theme this way (container.ts, screens-config.ts, etc.) already guards against this with a falsy/|| {} check — this file was the one outlier still using in.

Fix

Swap the 'keyframes' in resolvedConfig.theme check for a truthy check on resolvedConfig.theme.keyframes itself, matching the pattern used elsewhere in compat/.

Test plan

  • Added a regression test to apply-keyframes-to-theme.test.ts: theme: { keyframes: null } no longer throws and correctly results in no keyframes.
  • Verified the new test fails with the exact reported crash on the code prior to this fix, and passes after.
  • pnpm vitest run — all 5008 tests in the tailwindcss package pass (5007 existing + 1 new), no regressions.
  • tsc --noEmit shows no new type errors introduced by this change (pre-existing, unrelated errors exist elsewhere in the monorepo from packages that require a built @tailwindcss/oxide native module).

Every sibling module (container.ts, screens-config.ts, etc.) defensively
falls back to an empty object when a resolved theme namespace is missing
or nullish. `keyframesToRules` used `'keyframes' in resolvedConfig.theme`
instead, which is true even when the value itself is `null` (the documented
way to clear a theme key), so `Object.entries(null)` threw and crashed
the whole build.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@koreahghg
koreahghg requested a review from a team as a code owner August 20, 2026 09:09
@greptile-apps

greptile-apps Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Confidence Score: 5/5

The PR appears safe to merge.

No blocking failure remains.

Reviews (2): Last reviewed commit: "Correct changelog wording and add extend..." | Re-trigger Greptile

@coderabbitai

coderabbitai Bot commented Aug 20, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3ed844e3-a118-4b7b-aee9-419afa7667ed

📥 Commits

Reviewing files that changed from the base of the PR and between afd20c6 and 9c3e06e.

📒 Files selected for processing (2)
  • CHANGELOG.md
  • packages/tailwindcss/src/compat/apply-keyframes-to-theme.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • CHANGELOG.md

Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review.


Walkthrough

The keyframe conversion guard now processes theme.keyframes only when it is truthy. Regression tests cover null theme.keyframes and null theme.extend.keyframes values. The changelog documents the fix for null theme.keyframes configuration.

Merge Risk: ⚪ Minimal · up to 9c3e0

This localized fix prevents builds from crashing when theme.keyframes is explicitly null, with regression coverage and no actionable merge-blocking risk remaining after normal checks and review.

🚥 Pre-merge checks | ✅ 4
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main fix for the crash caused by an explicit null value in theme.keyframes.
Description check ✅ Passed The description accurately explains the crash, the fix, the regression tests, and the validation results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1


ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: e0619246-a2f1-47bf-8ae7-86a5a15c392e

📥 Commits

Reviewing files that changed from the base of the PR and between 90f8ff4 and afd20c6.

📒 Files selected for processing (3)
  • CHANGELOG.md
  • packages/tailwindcss/src/compat/apply-keyframes-to-theme.test.ts
  • packages/tailwindcss/src/compat/apply-keyframes-to-theme.ts

Included review availability: Your plan provides up to 10 included reviews per hour; 9 remain after this review.

Comment thread packages/tailwindcss/src/compat/apply-keyframes-to-theme.test.ts
theme.extend.keyframes: null never actually crashed: deepMerge skips
null/undefined sources entirely, so the resolved value there is `{}`,
not `null`. Drop the inaccurate "(or theme.extend.keyframes)" changelog
claim and add a dedicated test for that path so a future change to
deepMerge/resolveConfig can't silently reintroduce a crash there too.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
@koreahghg

Copy link
Copy Markdown
Contributor Author

Thanks for the review!

Re: the suggestion to also cover `theme.extend.keyframes: null` — good catch that it wasn't covered, but worth noting that path never actually hit the crash: `deepMerge` skips `null`/`undefined` sources entirely (see `compat/config/deep-merge.ts`), so the resolved value there is always `{}`, not `null`. I've pushed a follow-up commit that:

  • corrects the changelog line, which incorrectly implied the `extend` path was also crashing
  • adds a dedicated regression test for `theme.extend.keyframes: null` anyway, so a future change to `deepMerge`/`resolveConfig` can't silently reintroduce a crash there too

Full suite still green (5009/5010, 1 pre-existing skip).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant