emotion-js/emotion · error · Error
speedy must be changed before any rules are inserted
Error message
speedy must be changed before any rules are inserted
What it means
Emotion's sheet has a speedy mode (uses CSSOM insertInstead of text nodes) for performance. Once any rule has been inserted (sheet.ctr !== 0), toggling speedy changes how earlier rules were rendered, so in development emotion throws to prevent inconsistent styling.
Source
Thrown at packages/css/src/create-instance.ts:96
const registeredStyles: string[] = []
const rawClassName = getRegisteredStyles(
registered,
registeredStyles,
className
)
if (registeredStyles.length < 2) {
return className
}
return rawClassName + css(registeredStyles)
}
let createEmotion = (options: Options): Emotion => {
let cache = createCache(options)
;(cache.sheet as CSSStyleSheet).speedy = function (value: boolean) {
if (isDevelopment && this.ctr !== 0) {
throw new Error('speedy must be changed before any rules are inserted')
}
this.isSpeedy = value
}
cache.compat = true
let css: Emotion['css'] = (
...args: (TemplateStringsArray | Interpolation<unknown>)[]
) => {
let serialized = serializeStyles(args, cache.registered, undefined)
insertStyles(cache, serialized, false)
return `${cache.key}-${serialized.name}`
}
let keyframes: Emotion['keyframes'] = (
...args: (TemplateStringsArray | Interpolation<unknown>)[]
) => {
let serialized = serializeStyles(args, cache.registered)View on GitHub (pinned to b882bcba85)
Solutions
- Call sheet.speedy(...) before rendering anything / before the first insert
- Set the `speedy` option at createCache/createEmotion time instead: createEmotion({ key, speedy: true })
- In tests, create a fresh cache per test and configure speedy before inserting
Example fix
// before
const emotion = createEmotion({ key: 'app' })
render(<App />)
emotion.sheet.speedy(true)
// after
const emotion = createEmotion({ key: 'app', speedy: true })
render(<App />) Defensive patterns
Strategy: validation
Validate before calling
if (cache.sheet.ctr === 0) {
cache.sheet.speedy(true);
} else {
console.warn('speedy can only be toggled before any rules are inserted');
} Type guard
const canToggleSpeedy = (sheet) => sheet.ctr === 0;
Try / catch
try {
emotion.sheet.speedy(true);
} catch (e) {
if (e.message.includes('speedy must be changed')) {
console.warn('Too late to toggle speedy; recreate the cache instead');
} else {
throw e;
}
} Prevention
- Set speedy via createCache/createEmotion options, not by patching the sheet after render
- Only toggle speedy in bootstrap code that runs before any insert
- In tests, build a fresh emotion instance per test before rendering
When it happens
Trigger: Calling sheet.speedy(true/false) after at least one style rule was inserted into the cache, typically by calling emotion.sheet.speedy after components have rendered.
Common situations: Trying to disable speedy for testing after app render, calling speedy inside effects after initial paint, or toggling it from devtools/test setup post-render.
Related errors
- @emotion/babel-plugin-jsx-pragmatic: You must specify `modul
- You have specified that '${importSource}' re-exports '${reex
- The 'autoLabel' option must be undefined, or one of the foll
- There is no transformer for the export '${exportName}' in '$
- The `runtime` option has been removed. If you want to config
AI-assisted analysis of emotion-js/emotion@b882bcba85 (2026-09-02).
Data as JSON: /api/errors/d8ad71c1195d7966.
Report an issue: GitHub.