Troubleshooting
Parser Errors
Section titled “Parser Errors”Closing Tag Mismatch
Section titled “Closing Tag Mismatch”Example error:
Closing tag `</span>` does not match opening tag `<div>`.Fix the nesting:
// Wrongrsx! { <div> <span>{"Text"}</div> </span>}
// Correctrsx! { <div> <span>{"Text"}</span> </div>}Unclosed Tag or Fragment
Section titled “Unclosed Tag or Fragment”Add the missing closing tag:
// Wrongrsx! { <div>{"Content"}}
// Correctrsx! { <div>{"Content"}</div>}Unexpected Child Token
Section titled “Unexpected Child Token”Bare identifiers are not children. Wrap expressions in braces:
// Wrongrsx! { <div>count</div> }
// Correctrsx! { <div>{count}</div> }String literals can be written directly:
rsx! { <div>"Count"</div> }For Loop Body Missing Braces
Section titled “For Loop Body Missing Braces”The loop body must be a braced RSX body:
// Wrongrsx! { <ul> {for item in items <li>{item}</li> } </ul>}
// Correctrsx! { <ul> {for item in items { <li>{item}</li> }} </ul>}Class Errors
Section titled “Class Errors”Unsupported Static Class in Strict Mode
Section titled “Unsupported Static Class in Strict Mode”rsx_strict! rejects unsupported static classes:
rsx_strict! { <div class="hover:bg-blue-500" />}Use a supported class, a direct GPUI method, when, or rsx_permissive! if ignoring unsupported classes is intentional.
Invalid Arbitrary Length
Section titled “Invalid Arbitrary Length”Arbitrary length classes must use supported units and finite values:
// Correctrsx! { <div class="w-[280px] max-w-[37.5%] gap-[14px]" /> }Sizing supports px, rem, percentages, and fractions. Spacing supports definite lengths such as px and rem; percentage spacing is rejected.
Invalid Arbitrary Color
Section titled “Invalid Arbitrary Color”Use supported hex, RGB, or RGBA forms:
rsx! { <div class="bg-[#ff0000] text-[rgb(15,23,42)] border-[rgba(15,23,42,0.35)]" />}RGBA alpha must be in the 0.0..=1.0 range.
Dynamic Class Is Ignored
Section titled “Dynamic Class Is Ignored”Dynamic classes use a runtime matcher. Unsupported tokens are ignored in permissive mode and warn once per call site in debug builds.
If a dynamic class must always be applied, prefer one of these:
rsx! { <div class="flex" w={px(width)} whenClass={(active, "bg-blue-500 text-white")} />}Use rsx_strict! to panic when an unsupported dynamic token is evaluated.
Conditional Attribute Errors
Section titled “Conditional Attribute Errors”when, whenSome, or whenClass Tuple Shape
Section titled “when, whenSome, or whenClass Tuple Shape”These attributes expect exactly two tuple values:
rsx! { <div when={(active, |el| el.bg(rgb(0x3b82f6)))} /> <div whenSome={(width, |el, w| el.w(px(w)))} /> <div whenClass={(active, "bg-blue-500 text-white")} />}whenClass Requires a String Literal
Section titled “whenClass Requires a String Literal”This is invalid:
let classes = "bg-blue-500";rsx! { <div whenClass={(active, classes)} />}Use when for dynamic styling, or put the literal directly in whenClass.
whenClass Rejects Stateful Classes
Section titled “whenClass Rejects Stateful Classes”overflow-scroll, overflow-x-scroll, and overflow-y-scroll need ID semantics. Use when with explicit GPUI calls:
rsx! { <div when={(scrollable, |el| el.overflow_scroll())} />}ID and Loop Errors
Section titled “ID and Loop Errors”Stateful Element in Loop Has No id or key
Section titled “Stateful Element in Loop Has No id or key”Repeated stateful elements need unique IDs:
// Wrongrsx! { <ul> {for item in &self.items { <li onClick={handler}>{item.name.as_str()}</li> }} </ul>}
// Correctrsx! { <ul> {for item in &self.items { <li key={item.id} onClick={handler}>{item.name.as_str()}</li> }} </ul>}key only matters when the element needs an ID. On plain layout rows, it is ignored.
Auto ID Changed After Refactor
Section titled “Auto ID Changed After Refactor”Auto IDs include source file, line, and column. If identity must survive moving code, use an explicit id:
rsx! { <button id="settings-save" onClick={handler}> {"Save"} </button>}Type Errors
Section titled “Type Errors”IntoElement Is Not Implemented
Section titled “IntoElement Is Not Implemented”Children must be valid GPUI child values. Handle Option values explicitly:
rsx! { <div>{self.optional_text.as_deref().unwrap_or("")}</div>}Or render conditionally:
rsx! { <div> {if let Some(text) = &self.optional_text { rsx! { <span>{text.as_str()}</span> } } else { rsx! { <span /> } }} </div>}Cannot Move Out of self
Section titled “Cannot Move Out of self”Iterate by reference:
rsx! { <ul> {for item in &self.items { <li>{item.name.as_str()}</li> }} </ul>}Mixed Fragment Root Types
Section titled “Mixed Fragment Root Types”Fragments expand to vec![...]. If root element concrete types differ, wrap them or erase the type:
rsx! { <div> {self.render_header()} {self.render_custom_button()} </div>}Runtime Issues
Section titled “Runtime Issues”UI Does Not Update
Section titled “UI Does Not Update”After mutating view state, call cx.notify() once:
onClick={cx.listener(|view, _, _window, cx| { view.count += 1; cx.notify();})}Also check that the rsx! expression is returned from render without a trailing semicolon:
fn render(&mut self, _window: &mut Window, _cx: &mut Context<Self>) -> impl IntoElement { rsx! { <div>{"Content"}</div> }}Events Do Not Fire
Section titled “Events Do Not Fire”Check the handler signature expected by the GPUI method you are calling. For repeated stateful event targets, ensure the element has a key or explicit id.
Styling Does Not Apply
Section titled “Styling Does Not Apply”Use rsx_expand! to inspect generated methods:
let preview = gpui_rsx::rsx_expand! { <div class="flex gap-4 bg-blue-500" />};Remember that GPUI-RSX is not Tailwind CSS. Unsupported variants such as hover:bg-blue-500 do not become hover styles.
Dependency Issues
Section titled “Dependency Issues”Duplicate GPUI Crates
Section titled “Duplicate GPUI Crates”If gpui-component types do not match your application types, inspect the dependency tree:
cargo tree --manifest-path demo/Cargo.toml --locked -i gpuiKeep all direct gpui and gpui_platform dependencies on the same Zed source and revision as the component library.
Demo Check Fails After Updating Dependencies
Section titled “Demo Check Fails After Updating Dependencies”Run:
cargo check --manifest-path demo/Cargo.toml --bins --lockedIf --locked fails because the lockfile needs changes, decide whether the GPUI target revision should intentionally move. Do not update the lockfile casually for application compatibility checks.
Getting Help
Section titled “Getting Help”When filing an issue, include:
- GPUI-RSX version.
- The resolved GPUI source and revision from
cargo tree -i gpui. - Minimal RSX snippet.
- Full compiler error or runtime symptom.
- Whether the issue reproduces in the
demo/crate.