{"title":"Troubleshooting","description":"Fix installation issues, runtime errors, and debug HORUS applications","slug":"getting-started/troubleshooting","content":"# Troubleshooting\n\nFix installation issues, runtime errors, and debug HORUS applications. Start with the quick diagnostic steps below, then jump to the specific section matching your symptom.\n\n## Prerequisites\n\n- HORUS installed ([Installation Guide](/getting-started/installation))\n- Access to a terminal in your project directory\n\n## Quick Reference\n\n| Script | Use When | What It Does |\n|--------|----------|--------------|\n| `./install.sh` | Install or update | Full installation from source |\n| `./uninstall.sh` | Remove HORUS | Complete removal |\n\n## Common Errors At a Glance\n\n| Error | Jump To | Quick Fix |\n|-------|---------|-----------|\n| `horus: command not found` | [Runtime Issues](#horus-command-not-found) | `export PATH=\"$HOME/.cargo/bin:$PATH\"` |\n| `Rust is not installed` | [Installation Issues](#installation-issues) | Install Rust via `rustup` |\n| `Failed to create Topic` | [Topic Creation Errors](#topic-creation-errors) | `horus clean --shm` |\n| `No such file or directory` (topic) | [Slashes in Topic Names](#no-such-file-or-directory-when-creating-topic) | Use dots, not slashes |\n| Subscriber never receives messages | [Topic Not Found](#topic-not-found--no-messages-received) | Check topic name match in `horus monitor` |\n| Application freezes | [Application Hangs](#application-hangs--deadlock) | Check for blocking calls in `tick()` |\n| Messages silently dropped | [Messages Dropped](#messages-silently-dropped) | Keep messages under slot size |\n| Version mismatch | [Version Mismatch](#version-mismatch-errors) | `horus run --clean` |\n| `HORUS source directory not found` | [Source Not Found](#horus-source-directory-not-found-rust-projects) | Set `$HORUS_SOURCE` |\n\n## Quick Diagnostic Steps\n\nWhen your HORUS application isn't working:\n\n1. **Check the Monitor**: Run `horus monitor` to see active nodes, topics, and message flow\n2. **Examine Logs**: Look for error messages in your terminal output\n3. **Verify Topics**: Ensure publisher and subscriber use exact same topic names\n4. **Check Shared Memory**: Run `horus clean --shm` to remove stale shared memory regions\n5. **Test Individually**: Run nodes one at a time to isolate the problem\n\n---\n\n## Updating HORUS\n\nTo update to the latest version:\n\n```bash\ncd /path/to/horus\ngit pull\n./install.sh\n```\n\n**To preview changes before updating:**\n```bash\ngit fetch\ngit log HEAD..@{u}  # See what's new\ngit pull\n./install.sh\n```\n\n**If you have uncommitted changes:**\n```bash\ngit stash\ngit pull\n./install.sh\ngit stash pop  # Restore your changes\n```\n\n---\n\n## Manual Recovery\n\n**Use when:** Build errors, corrupted cache, installation broken\n\n### Quick Steps\n\n```bash\n# Navigate to HORUS source directory\ncd /path/to/horus\n\n# 1. Clean build artifacts\ncargo clean\n\n# 2. Remove cached libraries\nrm -rf ~/.horus/cache\n\n# 3. Fresh install\n./install.sh\n```\n\n### When to Use Recovery\n\n**Symptoms requiring recovery:**\n\n1. **Build fails:**\n   ```\n   error: could not compile `horus_core`\n   ```\n\n2. **Corrupted cache:**\n   ```\n   error: failed to load source for dependency `horus_core`\n   ```\n\n3. **Binary doesn't work:**\n   ```bash\n   $ horus --help\n   Segmentation fault\n   ```\n\n4. **Version mismatches:**\n   ```\n   error: the package `horus` depends on `horus_core 0.1.0`,\n   but `horus_core 0.1.3` is installed\n   ```\n\n5. **Broken after system updates:**\n   - Rust updated\n   - System libraries changed\n   - GCC/Clang updated\n\n### What Gets Removed\n\n**By `cargo clean`:**\n- `target/` directory (build artifacts)\n\n**By `rm -rf ~/.horus/cache`:**\n- Installed libraries\n- Cached dependencies\n\n**Never removed (safe):**\n- `~/.horus/config` (user settings)\n- `~/.horus/credentials` (registry auth)\n- Project-local `.horus/` directories\n- Your source code\n\n### Full Reset (Nuclear Option)\n\nIf the quick steps don't work, do a complete reset:\n\n```bash\n# Remove everything HORUS-related\ncargo clean\nrm -rf ~/.horus\nrm -f ~/.cargo/bin/horus\n\n# Fresh install\n./install.sh\n```\n\n---\n\n## Installation Issues\n\n**Problem: \"Rust not installed\"**\n\n```bash\n$ ./install.sh\n Error: Rust is not installed\n```\n\n**Solution:**\n```bash\n# Install Rust\ncurl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh\n\n# Then try again\n./install.sh\n```\n\n---\n\n**Problem: \"C compiler not found\"**\n\n**Solution:**\n```bash\n# Ubuntu/Debian/Raspberry Pi OS - Install ALL required packages\nsudo apt update\nsudo apt install -y build-essential pkg-config \\\n  libssl-dev libudev-dev libasound2-dev \\\n  libx11-dev libxrandr-dev libxi-dev libxcursor-dev libxinerama-dev \\\n  libwayland-dev wayland-protocols libxkbcommon-dev \\\n  libvulkan-dev libfontconfig-dev libfreetype-dev \\\n  libv4l-dev\n\n# Fedora/RHEL\nsudo dnf groupinstall \"Development Tools\"\nsudo dnf install -y pkg-config openssl-devel systemd-devel alsa-lib-devel \\\n  libX11-devel libXrandr-devel libXi-devel libXcursor-devel libXinerama-devel \\\n  wayland-devel wayland-protocols-devel libxkbcommon-devel \\\n  vulkan-devel fontconfig-devel freetype-devel \\\n  libv4l-devel\n```\n\n---\n\n**Problem: Build fails with linker errors**\n\n```\nerror: linking with `cc` failed: exit status: 1\nerror: could not find native static library `X11`, perhaps an -L flag is missing?\n```\n\n**Solution:**\n```bash\n# Install ALL missing system libraries (most common cause)\n# Ubuntu/Debian/Raspberry Pi OS\nsudo apt update\nsudo apt install -y build-essential pkg-config \\\n  libssl-dev libudev-dev libasound2-dev \\\n  libx11-dev libxrandr-dev libxi-dev libxcursor-dev libxinerama-dev \\\n  libwayland-dev wayland-protocols libxkbcommon-dev \\\n  libvulkan-dev libfontconfig-dev libfreetype-dev \\\n  libv4l-dev\n\n# Or run manual recovery (see Manual Recovery section)\ncargo clean && rm -rf ~/.horus/cache && ./install.sh\n```\n\n---\n\n## Update Issues\n\n**Problem: \"Build failed\" during update**\n\n**Solution:**\n```bash\n# Try manual recovery\ncargo clean && rm -rf ~/.horus/cache && ./install.sh\n```\n\n---\n\n**Problem: \"Already up to date\" but binary broken**\n\n**Solution:**\n```bash\n# Force rebuild\n./install.sh\n```\n\n---\n\n## Runtime Issues\n\n### \"horus: command not found\"\n\n**Solution:**\n```bash\n# Add to PATH (add to ~/.bashrc or ~/.zshrc)\nexport PATH=\"$HOME/.cargo/bin:$PATH\"\n\n# Then reload shell\nsource ~/.bashrc  # or restart terminal\n\n# Verify\nwhich horus\nhorus --help\n```\n\n---\n\n### Binary exists but doesn't run\n\n```bash\n$ horus --help\nSegmentation fault\n```\n\n**Solution:**\n```bash\n# Full recovery\ncargo clean && rm -rf ~/.horus/cache && ./install.sh\n```\n\n---\n\n### Version mismatch errors\n\n```\nerror: the package `horus` depends on `horus_core 0.1.0`,\nbut `horus_core 0.1.3` is installed\n```\n\n**Why this happens:**\n- You updated the `horus` CLI to a new version\n- Your project's `.horus/` directory still has cached dependencies from the old version\n- The cached `Cargo.lock` references incompatible library versions\n\n**Solution (Recommended - Fast & Easy):**\n```bash\n# Clean cached build artifacts and dependencies\nhorus run --clean\n\n# This removes .horus/target/ and forces a fresh build\n# with the new version\n```\n\n**Alternative Solutions:**\n\n**Option 2: Manual cleanup**\n```bash\n# Remove the entire .horus directory\nrm -rf .horus/\n\n# Next run will rebuild from scratch\nhorus run\n```\n\n**Option 3: Manual recovery (for persistent issues)**\n```bash\n# Only needed if --clean doesn't work\n# This reinstalls HORUS libraries globally\ncd /path/to/horus\ncargo clean && rm -rf ~/.horus/cache && ./install.sh\n```\n\n**For multiple projects:**\n```bash\n# Clean all projects in your workspace\nfind ~/your-projects -type d -name \".horus\" -exec rm -rf {}/target/ \\;\n```\n\n---\n\n### \"HORUS source directory not found\" (Rust projects)\n\n```\nError: HORUS source directory not found. Please set HORUS_SOURCE environment variable.\n```\n\n**Solution:**\n```bash\n# Option 1: Set HORUS_SOURCE (recommended for non-standard installations)\nexport HORUS_SOURCE=/path/to/horus\necho 'export HORUS_SOURCE=/path/to/horus' >> ~/.bashrc\n\n# Option 2: Install HORUS to a standard location\n# The CLI checks these paths automatically:\n#   - ~/softmata/horus\n#   - /horus\n#   - /opt/horus\n#   - /usr/local/horus\n\n# Verify HORUS source is found\nhorus build\n```\n\n**Why this happens:**\n- `horus run` needs to find HORUS core libraries for Rust compilation\n- It auto-detects standard installation paths\n- For custom installations, set `$HORUS_SOURCE`\n\n---\n\n## Topic Creation Errors\n\n**Symptom**: Application crashes on startup with:\n```\nError: Failed to create `Topic<MyMessage>`\nthread 'main' panicked at 'called `Result::unwrap()` on an `Err` value'\n```\n\n**Common Causes:**\n\n1. **Stale Shared Memory from Previous Run**\n   - If your app crashes, shared memory regions can persist\n\n   **Fix**: Clean shared memory:\n   ```bash\n   horus clean --shm\n   ```\n\n2. **Insufficient Permissions on Shared Memory** (Linux)\n\n   **Fix**: Ensure the shared memory directory has correct permissions, then clean stale regions:\n   ```bash\n   horus doctor        # Diagnoses permission issues\n   horus clean --shm   # Clean stale regions\n   ```\n\n3. **Insufficient Shared Memory Space**\n\n   **Fix**: Run the health check to see available space:\n   ```bash\n   horus doctor\n   ```\n   Consult your OS documentation to increase tmpfs size if needed.\n\n4. **Conflicting Topic Names**\n   - Two Topics with same name but different types\n\n   **Fix**: Use unique topic names:\n   ```rust\n   // BAD: Same name, different types\n   let topic1: Topic<f32> = Topic::new(\"data\")?;\n   let topic2: Topic<String> = Topic::new(\"data\")?;  // CONFLICT!\n\n   // GOOD: Different names\n   let topic1: Topic<f32> = Topic::new(\"sensor_data\")?;\n   let topic2: Topic<String> = Topic::new(\"status_data\")?;\n   ```\n\n**General Code Fix:**\n```rust\n// simplified\n// Topic names become file paths on the underlying shared memory system.\n// Use simple, descriptive names with dots (not slashes):\nlet topic = Topic::new(\"sensor_data\")?;\nlet topic = Topic::new(\"camera.front.raw\")?;\n```\n\n---\n\n### \"No such file or directory\" when creating Topic\n\n**Symptom**: Application crashes with:\n```\nthread 'main' panicked at 'Failed to create publisher 'camera': No such file or directory'\n```\n\n**Cause**: You're using **slashes (`/`)** in your topic name. While slashes work on Linux (parent directories are created automatically), they fail on **macOS** where shared memory uses `shm_open()` which doesn't support embedded slashes.\n\nOn Linux, topic names map to shared memory files. On macOS, they map to `shm_open()` kernel objects which don't support slashes:\n\n```\nTopic: \"sensors.camera\"  →  works on all platforms (cross-platform)\nTopic: \"sensors.camera\"  →  works on Linux only, fails on macOS\n```\n\n**Fix**: Use dots instead of slashes for cross-platform compatibility:\n\n```rust\n// WRONG - slashes fail on macOS\nlet topic: Topic<f32> = Topic::new(\"sensors/camera\")?;\nlet topic: Topic<Twist> = Topic::new(\"robot/cmd_vel\")?;\n\n// CORRECT - dots work on all platforms\nlet topic: Topic<f32> = Topic::new(\"sensors.camera\")?;\nlet topic: Topic<Twist> = Topic::new(\"robot.cmd_vel\")?;\n```\n\n**Coming from ROS?** ROS uses slashes (`/sensor/lidar`) because it uses network-based naming. HORUS uses dots because topic names map directly to shared memory file names. See [Topic Naming](/concepts/core-concepts-topic#use-dots-not-slashes) for details.\n\n---\n\n## Topic Not Found / No Messages Received\n\n**Symptom**: Subscriber node never receives messages even though publisher is sending.\n```rust\n// simplified\n// recv() always returns None\nif let Some(data) = self.data_sub.recv() {\n    println!(\"Got data\");  // Never prints\n}\n```\n\n**Common Causes:**\n\n1. **Topic Name Mismatch (Typo)**\n   - This is the #1 cause\n\n   **Fix**: Verify exact topic names:\n   ```rust\n   // Publisher\n   let pub_topic: Topic<f32> = Topic::new(\"sensor_data\")?;  // Note: sensor_data\n\n   // Subscriber (TYPO! Missing underscore)\n   let sub_topic: Topic<f32> = Topic::new(\"sensordata\")?;\n\n   // CORRECT:\n   let sub_topic: Topic<f32> = Topic::new(\"sensor_data\")?;  // Exact match\n   ```\n\n   **Debug with Monitor:**\n   ```bash\n   horus monitor\n   ```\n   Check the \"Topics\" section to see active topic names.\n\n2. **Type Mismatch**\n   - Publisher and subscriber use different message types\n\n   **Fix**: Ensure both use same type:\n   ```rust\n   // Publisher\n   let pub_topic: Topic<f32> = Topic::new(\"data\")?;\n   pub_topic.send(3.14);\n\n   // Subscriber (WRONG TYPE)\n   let sub_topic: Topic<f64> = Topic::new(\"data\")?;  // f64 != f32\n\n   // CORRECT:\n   let sub_topic: Topic<f32> = Topic::new(\"data\")?;  // Same type\n   ```\n\n3. **Publisher Hasn't Sent Yet**\n   - Subscriber starts before publisher sends first message\n   - This is normal! First `recv()` will return `None`\n\n   **Fix**: Check multiple ticks:\n   ```rust\n   impl Node for SubscriberNode {\n       fn tick(&mut self) {\n           if let Some(msg) = self.topic.recv() {\n               // Process message\n           } else {\n               // No message yet - this is OK on first few ticks\n           }\n       }\n   }\n   ```\n\n4. **Wrong Priority Order**\n   - Subscriber runs before publisher in same tick\n\n   **Fix**: Set priorities correctly:\n   ```rust\n   // Publisher should run first (lower order number)\n   scheduler.add(PublisherNode::new()?).order(0).build()?;\n\n   // Subscriber runs after (higher order number)\n   scheduler.add(SubscriberNode::new()?).order(1).build()?;\n   ```\n\n---\n\n## Application Hangs / Deadlock\n\n**Symptom**: Your app starts but freezes with no error messages.\n```\nStarting application...\n[Nodes initialized]\n[Application freezes - no output]\n```\n\n**Common Causes:**\n\n1. **Infinite Loop in `tick()`**\n   ```rust\n   // BAD: Never returns!\n   fn tick(&mut self) {\n       loop {\n           // Process data\n       }\n   }\n\n   // GOOD: Tick returns after work\n   fn tick(&mut self) {\n       self.process_data();\n       // Return naturally — scheduler calls tick() again next frame\n   }\n   ```\n\n2. **Blocking Operations in `tick()`**\n   ```rust\n   // BAD: Blocks scheduler\n   fn tick(&mut self) {\n       std::thread::sleep(Duration::from_secs(10));  // Blocks everything!\n   }\n\n   // GOOD: Use tick counter for delays\n   fn tick(&mut self) {\n       self.tick_count += 1;\n\n       // Execute every 10 ticks (~167ms at 60 FPS)\n       if self.tick_count % 10 == 0 {\n           self.slow_operation();\n       }\n   }\n   ```\n\n3. **Waiting Forever for Messages**\n   ```rust\n   // BAD: Blocking wait\n   fn tick(&mut self) {\n       while self.data_sub.recv().is_none() {\n           // Infinite loop if no messages!\n       }\n   }\n\n   // GOOD: Non-blocking receive\n   fn tick(&mut self) {\n       if let Some(data) = self.data_sub.recv() {\n           // Process data\n       }\n       // Continue even if no message\n   }\n   ```\n\n4. **Circular Priority Dependencies**\n   - Node A waits for Node B, Node B waits for Node A\n\n   **Fix**: Ensure data flows one direction:\n   ```rust\n   // BAD: Circular dependency\n   // Node A (priority 0) subscribes to \"data_b\"\n   // Node B (priority 1) subscribes to \"data_a\"\n   // Both wait for each other!\n\n   // GOOD: Unidirectional flow\n   // Node A (priority 0) publishes to \"data_a\"\n   // Node B (priority 1) subscribes to \"data_a\", publishes to \"data_b\"\n   // Node C (priority 2) subscribes to \"data_b\"\n   ```\n\n5. **Debug with Logging**\n   ```rust\n   fn tick(&mut self) {\n       hlog!(debug, \"Tick started\");\n       // Your code here\n       hlog!(debug, \"Tick completed\");\n   }\n   ```\n   If you see \"Tick started\" but never \"Tick completed\", the hang is in your code.\n\n---\n\n## Messages Silently Dropped\n\n**Symptom**: Publisher sends messages but subscriber never receives them, and no error is reported.\n\n**Cause**: For non-POD (serialized) messages, the serialized data exceeds the slot size (default 8KB). The `send()` method is lossy — it retries briefly then drops the message, incrementing an internal failure counter.\n\n**Fix**:\n\n**1. Check Message Size:**\n```rust\nuse std::mem::size_of;\n\n// POD messages always fit (slot = size_of::<T>())\n// Non-POD messages must serialize within the slot size (default 8KB)\nprintln!(\"Message size: {} bytes\", size_of::<MyMessage>());\n```\n\n**2. Keep Messages Reasonably Sized:**\n```rust\n// simplified\n// BAD: Variable size — may exceed limit\n#[derive(Clone, Serialize, Deserialize)]\npub struct LargeMessage {\n    pub data: Vec<u8>,\n}\n\n// GOOD: Fixed size\n#[derive(Clone, Serialize, Deserialize)]\npub struct LargeMessage {\n    pub data: [u8; 4096],  // Fixed 4KB\n}\n\n// BETTER: Split into multiple messages\n#[derive(Clone, Serialize, Deserialize)]\npub struct MessageChunk {\n    pub chunk_id: u32,\n    pub total_chunks: u32,\n    pub data: [u8; 1024],\n}\n```\n\n**3. Use Monitor to Check:**\n```bash\n# The monitor shows send failure counts per topic\nhorus monitor\n```\n\n---\n\n## Build and Compilation Issues\n\n### \"unresolved import\" or \"cannot find type in this scope\"\n\n**Symptom**: Code won't compile, missing types or functions.\n\n**Fix**: Ensure HORUS is in your `Cargo.toml` dependencies:\n\n```toml\n[dependencies]\nhorus = { path = \"...\" }\nhorus-robotics = { path = \"...\" }  # For robotics messages (CmdVel, Imu, LaserScan, etc.)\nhorus-tf = { path = \"...\" }        # For TransformFrame\n```\n\nImport the relevant preludes:\n```rust\nuse horus::prelude::*;             // Core runtime, topics, scheduler, horus_types\nuse horus_robotics::prelude::*;    // CmdVel, Imu, LaserScan, etc.\nuse horus_tf::prelude::*;          // TransformFrame and transforms\n```\n\n### \"trait bound ... is not satisfied\"\n\n**Symptom**: Compiler says your message doesn't implement required traits.\n\n**Fix**: Add required derives:\n```rust\n// simplified\n// Add these three derives to all messages\n#[derive(Debug, Clone, Serialize, Deserialize)]\npub struct MyMessage {\n    pub field: f32,\n}\n```\n\n---\n\n## Performance Issues\n\n**Problem: Slow builds**\n\n**Solution:**\n```bash\n# Use release mode (optimized)\nhorus run --release\n```\n\n---\n\n**Problem: Large disk usage**\n\n**Solution:**\n```bash\n# Clean old cargo cache\ncargo clean\n\n# Remove unused dependencies\ncargo install cargo-cache\ncargo cache --autoclean\n```\n\n---\n\n**Problem: Large `.horus/target/` directory (Rust projects)**\n\n**Why this happens:**\n- Cargo stores build artifacts in `.horus/target/`\n- Debug builds are unoptimized and larger\n- Incremental compilation caches intermediate files\n\n**Solution:**\n```bash\n# Clean build artifacts in current project\nrm -rf .horus/target/\n\n# Or use horus clean flag (next build will be slower)\nhorus run --clean\n\n# Regular cleanup (if working on multiple projects)\nfind . -type d -name \".horus\" -exec rm -rf {}/target/ \\;\n\n# Add to .gitignore (already included in horus new templates)\necho \".horus/target/\" >> .gitignore\n```\n\n**Disk usage typical sizes:**\n- `.horus/target/debug/`: ~10-100 MB (incremental builds)\n- `.horus/target/release/`: ~5-50 MB (optimized, no debug symbols)\n\n**Best practices:**\n- `.horus/` is in `.gitignore` by default\n- Clean periodically if disk space is limited\n\n---\n\n## Using the Monitor to Debug\n\nThe monitor is your best debugging tool for runtime issues.\n\n**Starting the Monitor:**\n```bash\n# Terminal 1: Run your application\nhorus run\n\n# Terminal 2: Start monitor\nhorus monitor\n```\n\n**Monitor Features:**\n\n**1. Nodes Tab:**\n- Shows all running nodes\n- Displays node state (Running, Error, Stopped)\n- Shows tick count and timing\n- Highlights nodes that aren't ticking (stuck)\n\n**2. Topics Tab:**\n- Lists all active topics\n- Shows message types\n- Displays publisher/subscriber counts\n- **0 publishers** = no one is sending\n- **0 subscribers** = no one is listening\n\n**3. Metrics Tab:**\n- **IPC Latency**: Communication time (should be &lt;1µs)\n- **Tick Duration**: How long each node takes\n- **Message Counts**: Total sent/received\n  - If sent > 0 but received = 0, subscriber issue\n  - If sent = 0, publisher issue\n\n**4. Graph Tab:**\n- Visual node graph\n- Shows message flow between nodes\n- Disconnected nodes = topic mismatch\n\n**Debug Workflow:**\n\n```\n1. Check Nodes tab\n   -> All nodes Running? (If Error, check logs)\n\n2. Check Topics tab\n   -> Topics exist? (If no, topic name typo)\n   -> Publishers > 0? (If no, publisher not working)\n   -> Subscribers > 0? (If no, subscriber not created)\n\n3. Check Metrics tab\n   -> Messages sent > 0? (If no, publisher not sending)\n   -> Messages received > 0? (If no, subscriber not receiving)\n   -> IPC latency sane? (If >1ms, system issue)\n\n4. Check Graph tab\n   -> Nodes connected? (If no, topic name mismatch)\n```\n\n**Example Debug Session:**\n\n```bash\n# Problem: Subscriber not receiving messages\n\n# Monitor shows:\n# Nodes: SensorNode (Running), DisplayNode (Running)\n# Topics: \"sensor_data\" (1 pub, 0 sub)  <-- AHA!\n\n# Issue: No subscribers!\n# Fix: Check DisplayNode - likely wrong topic name\n```\n\n---\n\n## Reading Log Output\n\n### Log Levels\n\nHORUS nodes can log at different severity levels:\n\n```rust\nfn tick(&mut self) {\n    hlog!(debug, \"Detailed info for debugging\");\n    hlog!(info, \"Normal informational message\");\n    hlog!(warn, \"Something unusual happened\");\n    hlog!(error, \"Something went wrong!\");\n}\n```\n\n### Log Format\n\nConsole output uses ANSI-colored formatting:\n\n```\n[INFO] [SensorNode] Sensor initialized\n│      │            │\n│      │            └─ Message\n│      └─ Node name\n└─ Log level (INFO, WARN, ERROR, DEBUG)\n```\n\nTimestamps are included in the shared memory log buffer (visible in the monitor), formatted as `HH:MM:SS.mmm`.\n\n---\n\n## Common Patterns and Anti-Patterns\n\n### [OK] DO: Check recv() for None\n\n```rust\nfn tick(&mut self) {\n    if let Some(msg) = self.topic.recv() {\n        // Process message\n    }\n    // No message? That's OK, just continue\n}\n```\n\n### [FAIL] DON'T: Unwrap recv()\n\n```rust\nfn tick(&mut self) {\n    let msg = self.topic.recv().unwrap();  // PANIC if no message!\n}\n```\n\n### [OK] DO: Use Result for errors\n\n```rust\n// simplified\nimpl Node for MyNode {\n    fn init(&mut self) -> Result<()> {\n        if self.sensor.is_broken() {\n            return Err(Error::node(\"MyNode\", \"Sensor initialization failed\"));\n        }\n        Ok(())\n    }\n}\n```\n\n### [FAIL] DON'T: panic!() in nodes\n\n```rust\nfn init(&mut self) -> Result<()> {\n    if self.sensor.is_broken() {\n        panic!(\"Sensor broken\");  // DON'T DO THIS\n    }\n    Ok(())\n}\n```\n\n### [OK] DO: Keep tick() fast\n\n```rust\nfn tick(&mut self) {\n    // Quick operations only\n    let data = self.sensor.read_cached();\n    self.topic.send(data);\n}\n```\n\n### [FAIL] DON'T: Block in tick()\n\n```rust\nfn tick(&mut self) {\n    thread::sleep(Duration::from_millis(100));  // Blocks everything!\n    let data = self.network.fetch();  // Network I/O blocks!\n}\n```\n\n---\n\n## Best Practices\n\n### Regular Maintenance\n\n**Weekly (active development):**\n```bash\ngit pull && ./install.sh  # Pulls latest and rebuilds\n```\n\n**After system updates:**\n```bash\n# If Rust/GCC updated, run manual recovery\ncargo clean && rm -rf ~/.horus/cache && ./install.sh\n```\n\n### CI/CD Integration\n\n```bash\n# In CI pipeline\n./install.sh || (cargo clean && rm -rf ~/.horus/cache && ./install.sh)\n```\n\n### Debugging Workflow\n\n1. **First: Check horus works**\n   ```bash\n   horus --help\n   ```\n\n2. **If issues: Update**\n   ```bash\n   git pull && ./install.sh\n   ```\n\n3. **If errors: Manual recovery**\n   ```bash\n   cargo clean && rm -rf ~/.horus/cache && ./install.sh\n   ```\n\n---\n\n## Getting Help\n\nIf you're still having issues:\n\n1. **Try manual recovery:**\n   ```bash\n   cargo clean && rm -rf ~/.horus/cache && ./install.sh\n   ```\n\n2. **Add Debug Logging:**\n   ```rust\n   // Add hlog!(debug, ...) in your nodes to trace execution\n   hlog!(debug, \"Node state: {:?}\", self.state);\n   ```\n\n3. **Test with Minimal Example:**\n   - Strip down to simplest possible code\n   - Add complexity back one piece at a time\n   - Identify what causes the error\n\n4. **Check System Resources:**\n   ```bash\n   # Check system health (includes shared memory)\n   horus doctor\n\n   # Clean stale shared memory if needed\n   horus clean --shm\n   ```\n\n5. **Report the issue:**\n   - GitHub: https://github.com/softmata/horus/issues\n   - Include: full error message, minimal code example, OS and platform\n\n---\n\n## Next Steps\n\n- **[Installation](/getting-started/installation)** - First-time installation guide\n- **[CLI Reference](/development/cli-reference)** - All horus commands\n- **[Examples](/rust/examples/basic-examples)** - Working code examples\n- **[Performance](/performance/performance)** - Optimization tips\n- **[Testing](/development/testing)** - Test your nodes to prevent runtime errors\n\n---\n\n## See Also\n\n- [Common Mistakes](/getting-started/common-mistakes) — Beginner pitfalls\n- [Debugging](/development/debugging) — Runtime diagnostics\n- [Monitor](/development/monitor) — Live system observation\n- [CLI Reference](/development/cli-reference) — `horus doctor` and `horus log`","headings":["Troubleshooting","Prerequisites","Quick Reference","Common Errors At a Glance","Quick Diagnostic Steps","Updating HORUS","Manual Recovery","Quick Steps","Navigate to HORUS source directory","1. Clean build artifacts","2. Remove cached libraries","3. Fresh install","When to Use Recovery","What Gets Removed","Full Reset (Nuclear Option)","Remove everything HORUS-related","Fresh install","Installation Issues","Install Rust","Then try again","Ubuntu/Debian/Raspberry Pi OS - Install ALL required packages","Fedora/RHEL","Install ALL missing system libraries (most common cause)","Ubuntu/Debian/Raspberry Pi OS","Or run manual recovery (see Manual Recovery section)","Update Issues","Try manual recovery","Force rebuild","Runtime Issues","\"horus: command not found\"","Add to PATH (add to ~/.bashrc or ~/.zshrc)","Then reload shell","Verify","Binary exists but doesn't run","Full recovery","Version mismatch errors","Clean cached build artifacts and dependencies","This removes .horus/target/ and forces a fresh build","with the new version","Remove the entire .horus directory","Next run will rebuild from scratch","Only needed if --clean doesn't work","This reinstalls HORUS libraries globally","Clean all projects in your workspace","\"HORUS source directory not found\" (Rust projects)","Option 1: Set HORUSSOURCE (recommended for non-standard installations)","Option 2: Install HORUS to a standard location","The CLI checks these paths automatically:","- ~/softmata/horus","- /horus","- /opt/horus","- /usr/local/horus","Verify HORUS source is found","Topic Creation Errors","\"No such file or directory\" when creating Topic","Topic Not Found / No Messages Received","Application Hangs / Deadlock","Messages Silently Dropped","The monitor shows send failure counts per topic","Build and Compilation Issues","\"unresolved import\" or \"cannot find type in this scope\"","\"trait bound ... is not satisfied\"","Performance Issues","Use release mode (optimized)","Clean old cargo cache","Remove unused dependencies","Clean build artifacts in current project","Or use horus clean flag (next build will be slower)","Regular cleanup (if working on multiple projects)","Add to .gitignore (already included in horus new templates)","Using the Monitor to Debug","Terminal 1: Run your application","Terminal 2: Start monitor","Problem: Subscriber not receiving messages","Monitor shows:","Nodes: SensorNode (Running), DisplayNode (Running)","Topics: \"sensordata\" (1 pub, 0 sub)  <-- AHA!","Issue: No subscribers!","Fix: Check DisplayNode - likely wrong topic name","Reading Log Output","Log Levels","Log Format","Common Patterns and Anti-Patterns","[OK] DO: Check recv() for None","[FAIL] DON'T: Unwrap recv()","[OK] DO: Use Result for errors","[FAIL] DON'T: panic!() in nodes","[OK] DO: Keep tick() fast","[FAIL] DON'T: Block in tick()","Best Practices","Regular Maintenance","If Rust/GCC updated, run manual recovery","CI/CD Integration","In CI pipeline","Debugging Workflow","Getting Help","Next Steps","See Also"],"wordCount":3373}