# Troubleshooting
Common issues and solutions when using GPUI-RSX.
## Compilation Errors
### Error: "closing tag does not match opening tag"
**Error message:**
```
Closing tag `</span>` does not match opening tag `<div>`. Tags must be properly nested.
```
**Solution:**
Ensure all tags are properly matched:
```rust
// ✗ Wrong
<div>
<span>"Text"</div>
</span>
// ✓ Correct
<div>
<span>"Text"</span>
</div>
```
### Error: "unclosed tag"
**Error message:**
```
Unclosed tag `<div>`. Expected closing tag before end of input.
```
**Solution:**
Add the missing closing tag:
```rust
// ✗ Wrong
rsx! {
<div>"Content"
}
// ✓ Correct
rsx! {
<div>"Content"</div>
}
```
### Error: "unexpected token"
**Error message:**
```
Unexpected token in `<div>`. Expected one of: {expr}, "text", <child>, or </div>
```
**Solution:**
Wrap bare identifiers in braces:
```rust
// ✗ Wrong
<div>count</div>
// ✓ Correct
<div>{count}</div>
```
### Error: "class attribute only supports string literals"
**Error message:**
```
class attribute only supports string literals; use individual attributes for dynamic styling
```
**Solution:**
Use individual attributes for dynamic values:
```rust
// ✗ Wrong
<div class={format!("flex {}", self.extra_classes)} />
// ✓ Correct
<div
flex
bg={self.get_background()}
/>
```
### Error: "expected '{' after for-in expression"
**Error message:**
```
Expected '{' after for-in expression to start the loop body.
```
**Solution:**
Add braces around the for-loop body:
```rust
// ✗ Wrong
{for item in items
<div>{item}</div>
}
// ✓ Correct
{for item in items {
<div>{item}</div>
}}
```
## Type Errors
### Error: "trait `IntoElement` is not implemented"
**Error:**
```
the trait `IntoElement` is not implemented for `Option<String>`
```
**Solution:**
Unwrap or handle the Option:
```rust
// ✗ Wrong
<div>{self.optional_text}</div>
// ✓ Correct - unwrap with default
<div>{self.optional_text.as_deref().unwrap_or("")}</div>
// ✓ Correct - conditional rendering
{if let Some(text) = &self.optional_text {
rsx! { <div>{text.as_str()}</div> }
}}
```
### Error: "mismatched types" in conditional
**Error:**
```
expected `Div`, found `Span`
```
**Solution:**
Both branches must return the same type. Use a common container:
```rust
// ✗ Wrong
fn render_content(&self) -> impl IntoElement {
if self.use_div {
rsx! { <div>"Content"</div> }
} else {
rsx! { <span>"Content"</span> }
}
}
// ✓ Correct - wrap in common type
fn render_content(&self) -> impl IntoElement {
rsx! {
<div>
{if self.use_bold {
rsx! { <strong>"Content"</strong> }
} else {
rsx! { <span>"Content"</span> }
}}
</div>
}
}
```
### Error: "cannot move out of `self`"
**Error:**
```
cannot move out of `self.items` which is behind a shared reference
```
**Solution:**
Use references in loops:
```rust
// ✗ Wrong
{for item in self.items {
<div>{item.name}</div>
}}
// ✓ Correct
{for item in &self.items {
<div>{item.name.as_str()}</div>
}}
```
## Runtime Issues
### Elements not appearing
**Symptoms:**
- Elements don't show up in the UI
- Layout is empty
**Possible causes and solutions:**
1. **Forgot to return from render:**
```rust
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
rsx! { <div>"Content"</div> }; }
fn render(&mut self, cx: &mut ViewContext<Self>) -> impl IntoElement {
rsx! { <div>"Content"</div> } }
```
2. **Missing `cx.notify()` after state changes:**
```rust
fn handle_click(&mut self, cx: &mut ViewContext<Self>) {
self.count += 1;
}
fn handle_click(&mut self, cx: &mut ViewContext<Self>) {
self.count += 1;
cx.notify(); }
```
3. **Size constraints:**
```rust
<div />
<div class="w-full h-full" />
```
### Events not firing
**Symptoms:**
- Clicks or other events don't trigger handlers
**Possible causes and solutions:**
1. **Element needs an ID for interactive events:**
RSX automatically adds IDs for elements with event handlers, but if you're getting issues:
```rust
<button id="my-button" onClick={handler}>
"Click"
</button>
```
2. **Element is covered by another element:**
Check z-index and layering:
```rust
<button class="relative z-10" onClick={handler}>
"Click"
</button>
```
3. **Handler signature is incorrect:**
```rust
onClick={cx.listener(|view, _event, cx| {
view.handle_click(cx);
})}
```
### Styling not applied
**Symptoms:**
- Colors, sizes, or other styles don't appear
**Possible causes and solutions:**
1. **Typo in class name:**
```rust
<div class="flex-collumn" />
<div class="flex-col" />
```
2. **Invalid color name:**
```rust
<div class="bg-blue-550" />
<div class="bg-blue-500" />
```
3. **Style override order:**
```rust
<div
bg={rgb(0xff0000)} class="bg-blue-500" />
```
### Performance issues
**Symptoms:**
- Slow rendering
- High CPU usage
- Laggy interactions
**Solutions:**
1. **Minimize cloning in loops:**
```rust
{for item in &self.items {
<div>{item.description.clone()}</div>
}}
{for item in &self.items {
<div>{item.description.as_str()}</div>
}}
```
2. **Extract static elements:**
```rust
rsx! {
<div>
<header class="flex p-4">"Static Header"</header>
{self.dynamic_content()}
</div>
}
fn render_static_header() -> impl IntoElement {
rsx! { <header class="flex p-4">"Static Header"</header> }
}
```
3. **Batch state updates:**
```rust
self.value1 = new_value1;
cx.notify();
self.value2 = new_value2;
cx.notify();
self.value1 = new_value1;
self.value2 = new_value2;
cx.notify();
```
## IDE Issues
### No syntax highlighting
**Solution:**
RSX syntax is valid Rust syntax, so standard Rust syntax highlighting should work. If you're experiencing issues:
1. **Restart your IDE/language server**
2. **Ensure rust-analyzer is up to date:**
```bash
rustup update
```
### No autocomplete in RSX
**Solution:**
Autocomplete inside `rsx!` macros is limited. For better IDE support:
1. **Extract complex logic to methods**
2. **Use explicit types:**
```rust
let items: &[Item] = &self.items;
rsx! {
<div>
{for item in items {
<div>{item.name.as_str()}</div>
}}
</div>
}
```
### Macro expansion errors
**Solution:**
View expanded macro output:
```bash
cargo expand --lib
```
Or for a specific module:
```bash
cargo expand --lib module_name
```
## Build Issues
### Long compile times
**Symptoms:**
- Slow incremental builds
- High CPU usage during compilation
**Solutions:**
1. **Use release mode for final builds only:**
```bash
cargo build ```
2. **Split large RSX blocks:**
```rust
rsx! {
<div>
</div>
}
fn render(&self) -> impl IntoElement {
rsx! {
<div>
{self.render_header()}
{self.render_body()}
{self.render_footer()}
</div>
}
}
```
3. **Update dependencies:**
```bash
cargo update
```
### Dependency conflicts
**Error:**
```
failed to select a version for `syn`
```
**Solution:**
Ensure compatible versions:
```toml
[dependencies]
gpui-rsx = "0.1"
syn = { version = "2.0", features = ["full"] }
```
## Getting Help
If you're still stuck:
1. **Enable debug logging:**
```rust
env_logger::init();
log::debug!("State: {:?}", self);
```
3. **Simplify to minimal reproduction:**
```rust
```
4. **Search existing issues:**
- [GPUI-RSX Issues](https://github.com/wsafight/gpui-rsx/issues)
- [GPUI Issues](https://github.com/zed-industries/gpui/issues)
5. **Create a new issue:**
Include:
- Minimal code example
- Error messages
- Expected vs actual behavior
- Rust version (`rustc --version`)
- GPUI version
- GPUI-RSX version
## Common Pitfalls
### Semicolon after rsx! macro
```rust
// ✗ Returns ()
rsx! { <div>"Content"</div> };
// ✓ Returns impl IntoElement
rsx! { <div>"Content"</div> }
```
### Forgetting braces around expressions
```rust
// ✗ Syntax error
<div>self.count</div>
// ✓ Correct
<div>{self.count}</div>
```
### Using `clone()` excessively
```rust
// ✗ Expensive
{for item in &self.items {
<div>{item.name.clone()}</div>
}}
// ✓ Cheaper
{for item in &self.items {
<div>{item.name.as_str()}</div>
}}
```
### Missing return type bounds
```rust
// ✗ May cause inference issues
fn render_item(&self, item: &Item) {
rsx! { <div>{item.name.as_str()}</div> }
}
// ✓ Explicit return type
fn render_item(&self, item: &Item) -> impl IntoElement {
rsx! { <div>{item.name.as_str()}</div> }
}
```