---
name: electrobun-debugging
description: Development workflow, debugging, and troubleshooting for Electrobun desktop applications. This skill covers debugging the main process (Bun) and webview processes, Chrome DevTools integration, console logging strategies, error handling, performance profiling, memory leak detection, build error troubleshooting, common runtime errors, development environment setup, hot reload configuration, source maps, breakpoint debugging, network inspection, WebView debugging on different platforms, native module debugging, and systematic debugging approaches. Use when encountering build failures, runtime errors, crashes, performance issues, debugging RPC communication, inspecting webview DOM, profiling CPU/memory usage, troubleshooting platform-specific issues, or setting up development workflow. Triggers include "debug", "error", "crash", "troubleshoot", "DevTools", "inspect", "breakpoint", "profiling", "performance issue", "build error", "not working", or "logging".
license: MIT
metadata:
author: Blackboard
version: "1.0.0"
---
# Electrobun Debugging
Comprehensive debugging and troubleshooting guide for Electrobun applications.
## Development Environment
### Basic Development Setup
```bash
# Development mode with hot reload
bun run dev
# Development mode with verbose logging
DEBUG=* bun run dev
# Development mode with specific debug namespace
DEBUG=electrobun:* bun run dev
```
### Environment Configuration
**.env.development:**
```bash
# Enable development features
NODE_ENV=development
DEBUG=electrobun:*
# DevTools always open
ELECTRON_ENABLE_DEVTOOLS=1
# Disable security warnings in dev
ELECTRON_DISABLE_SECURITY_WARNINGS=true
# Custom dev server port
DEV_SERVER_PORT=3000
```
## Debugging Main Process
### Console Logging
```ts
// Main process logs appear in terminal
console.log("Main process started");
console.error("Error in main process");
console.warn("Warning in main process");
// Structured logging
const logger = {
debug: (msg: string, data?: any) => {
if (process.env.DEBUG) {
console.log(`[DEBUG] ${msg}`, data || "");
}
},
info: (msg: string, data?: any) => {
console.log(`[INFO] ${msg}`, data || "");
},
error: (msg: string, error?: any) => {
console.error(`[ERROR] ${msg}`, error || "");
if (error?.stack) {
console.error(error.stack);
}
}
};
logger.info("Window created", { width: 1200, height: 800 });
logger.error("Failed to load file", error);
```
### Bun Debugger
```bash
# Start with Bun debugger
bun --inspect run dev
# With breakpoint on first line
bun --inspect-brk run dev
# Connect with Chrome DevTools
# Open chrome://inspect in Chrome
# Click "inspect" on your process
```
### Error Handling in Main
```ts
// Global error handlers
process.on("uncaughtException", (error) => {
logger.error("Uncaught exception", error);
// Show error dialog
dialog.showMessageBox({
type: "error",
title: "Application Error",
message: "An unexpected error occurred",
detail: error.message,
});
// Optional: restart or quit
// app.relaunch();
// app.quit();
});
process.on("unhandledRejection", (reason, promise) => {
logger.error("Unhandled rejection", { reason, promise });
});
// Window error handler
win.on("error", (error) => {
logger.error("Window error", error);
});
// RPC error handling
win.defineRpc({
handlers: {
async someHandler(args: any) {
try {
// Handler logic
return { success: true };
} catch (error) {
logger.error("RPC handler error", error);
throw error; // Re-throw to send to webview
}
}
}
});
```
## Debugging Webview
### Chrome DevTools
```ts
// Open DevTools programmatically
win.openDevTools();
// Open DevTools detached
win.openDevTools({ mode: "detach" });
// Toggle DevTools
win.toggleDevTools();
// Close DevTools
win.closeDevTools();
// Menu item to toggle DevTools
{
label: "Toggle Developer Tools",
accelerator: "CmdOrCtrl+Shift+I",
action: () => win.toggleDevTools()
}
```
### Console Logging in Webview
```ts
// Webview console logs appear in DevTools
console.log("Webview initialized");
console.error("Error in webview");
console.warn("Warning in webview");
console.table({ user: "Alice", age: 30 });
// Custom logger
const logger = {
log: (msg: string, ...args: any[]) => {
console.log(`[${new Date().toISOString()}] ${msg}`, ...args);
},
group: (label: string) => {
console.group(label);
},
groupEnd: () => {
console.groupEnd();
}
};
logger.group("User Login");
logger.log("Validating credentials");
logger.log("Fetching user data");
logger.groupEnd();
```
### Capturing Webview Errors
```ts
// Global error handler
window.addEventListener("error", (event) => {
console.error("Uncaught error:", event.error);
// Send to main process for logging
electroview.rpc.logError({
message: event.error.message,
stack: event.error.stack,
url: event.filename,
line: event.lineno,
column: event.colno,
});
});
// Unhandled promise rejections
window.addEventListener("unhandledrejection", (event) => {
console.error("Unhandled rejection:", event.reason);
electroview.rpc.logError({
message: "Unhandled rejection",
reason: event.reason,
});
});
// Main process handler
win.defineRpc({
handlers: {
async logError(error: any) {
logger.error("Webview error", error);
// Optional: save to file
await saveErrorLog(error);
}
}
});
```
## Debugging RPC Communication
### RPC Logging
```ts
// Main process RPC logger
class RpcLogger {
wrap(handlers: any) {
const wrapped: any = {};
for (const [name, handler] of Object.entries(handlers)) {
wrapped[name] = async (...args: any[]) => {
const callId = Math.random().toString(36).slice(2);
logger.debug(`[RPC:${callId}] → ${name}`, args);
const startTime = Date.now();
try {
const result = await (handler as Function)(...args);
const duration = Date.now() - startTime;
logger.debug(`[RPC:${callId}] ← ${name} (${duration}ms)`, result);
return result;
} catch (error) {
const duration = Date.now() - startTime;
logger.error(`[RPC:${callId}] ✗ ${name} (${duration}ms)`, error);
throw error;
}
};
}
return wrapped;
}
}
const rpcLogger = new RpcLogger();
win.defineRpc({
handlers: rpcLogger.wrap({
async getUser(id: string) {
return await database.users.findById(id);
},
async saveFile(path: string, content: string) {
await Bun.write(path, content);
return { success: true };
}
})
});
```
### Testing RPC in DevTools
```ts
// In webview DevTools console:
// Test RPC call
await electroview.rpc.getUser("123")
// Test error handling
try {
await electroview.rpc.invalidMethod()
} catch (error) {
console.error("Expected error:", error);
}
// Measure RPC performance
console.time("RPC call");
const result = await electroview.rpc.getUser("123");
console.timeEnd("RPC call");
```
## Performance Profiling
### CPU Profiling
```ts
// Main process CPU profiling
const { performance, PerformanceObserver } = require("perf_hooks");
const obs = new PerformanceObserver((items) => {
items.getEntries().forEach(entry => {
logger.debug(`${entry.name}: ${entry.duration}ms`);
});
});
obs.observe({ entryTypes: ["measure"] });
// Measure operation
performance.mark("operation-start");
await expensiveOperation();
performance.mark("operation-end");
performance.measure("operation", "operation-start", "operation-end");
```
**Webview CPU profiling:**
```ts
// Use Chrome DevTools Performance tab
// Or programmatically:
console.profile("My Operation");
await performOperation();
console.profileEnd("My Operation");
// Simple timing
const start = performance.now();
await operation();
const duration = performance.now() - start;
console.log(`Operation took ${duration}ms`);
```
### Memory Profiling
```ts
// Main process memory usage
function logMemoryUsage() {
const usage = process.memoryUsage();
logger.info("Memory usage", {
heapUsed: `${Math.round(usage.heapUsed / 1024 / 1024)}MB`,
heapTotal: `${Math.round(usage.heapTotal / 1024 / 1024)}MB`,
external: `${Math.round(usage.external / 1024 / 1024)}MB`,
rss: `${Math.round(usage.rss / 1024 / 1024)}MB`,
});
}
// Monitor memory over time
setInterval(logMemoryUsage, 10000);
// Force garbage collection (development only)
if (global.gc) {
global.gc();
logMemoryUsage();
}
```
**Webview memory profiling:**
```ts
// Use Chrome DevTools Memory tab
// Or programmatically:
if (performance.memory) {
console.log("Memory:", {
used: `${Math.round(performance.memory.usedJSHeapSize / 1024 / 1024)}MB`,
total: `${Math.round(performance.memory.totalJSHeapSize / 1024 / 1024)}MB`,
limit: `${Math.round(performance.memory.jsHeapSizeLimit / 1024 / 1024)}MB`,
});
}
```
## Common Issues & Solutions
### Build Errors
**Issue: "Cannot find module 'electrobun'"**
```bash
# Solution: Install dependencies
bun install
# Verify electrobun is installed
bun pm ls electrobun
```
**Issue: Native module compilation fails**
```bash
# macOS: Install Xcode Command Line Tools
xcode-select --install
# Windows: Install Visual Studio Build Tools
# Download from visualstudio.microsoft.com
# Linux: Install build essentials
sudo apt install build-essential
```
**Issue: "WebView2 not found" (Windows)**
```bash
# Install WebView2 Runtime
# Download from microsoft.com/edge/webview2
```
### Runtime Errors
**Issue: Window not showing**
```ts
// Debug checklist:
// 1. Check window is created
console.log("Window created:", win);
// 2. Explicitly show window
win.show();
// 3. Check window bounds
console.log("Window bounds:", win.getBounds());
// 4. Check if window is minimized/hidden
console.log("Window visible:", win.isVisible());
console.log("Window minimized:", win.isMinimized());
```
**Issue: RPC not working**
```ts
// Debug checklist:
// 1. Verify RPC handlers defined
console.log("RPC handlers:", Object.keys(handlers));
// 2. Check webview loaded
win.on("did-finish-load", () => {
console.log("Webview loaded");
});
// 3. Test RPC with try-catch
try {
const result = await electroview.rpc.testMethod();
console.log("RPC working:", result);
} catch (error) {
console.error("RPC error:", error);
}
// 4. Check for CORS issues in webview
// 5. Verify Electroview initialized in webview
```
**Issue: High memory usage**
```ts
// Common causes:
// 1. Memory leaks from event listeners
window.removeEventListener("resize", handler);
// 2. Large data stored in closures
// Use WeakMap/WeakSet for object references
// 3. Not cleaning up resources
win.on("close", () => {
// Clean up timers
clearInterval(intervalId);
// Close connections
ws.close();
// Release resources
cache.clear();
});
```
### Platform-Specific Issues
**macOS:**
```ts
// Issue: App won't open (Gatekeeper)
// Solution: Code sign and notarize
// Issue: Permissions denied
// Solution: Add Info.plist entries
NSCameraUsageDescription
App needs camera access
NSMicrophoneUsageDescription
App needs microphone access
```
**Windows:**
```ts
// Issue: SmartScreen warning
// Solution: Code sign with trusted certificate
// Issue: Antivirus blocking
// Solution: Code sign and submit to vendors
```
**Linux:**
```ts
// Issue: WebKit crashes
// Solution: Install webkit2gtk-4.1
sudo apt install libwebkit2gtk-4.1-dev
// Issue: Missing libraries
// Solution: Check dependencies
ldd dist/MyApp
```
## Debugging Tools
### Network Inspection
```ts
// Intercept network requests
win.on("will-navigate", (event) => {
logger.debug("Navigating to:", event.url);
// Block navigation if needed
if (event.url.includes("blocked.com")) {
event.preventDefault();
}
});
// Monitor requests in DevTools Network tab
// Or programmatically:
win.webContents.session.webRequest.onBeforeRequest((details, callback) => {
logger.debug("Request:", details.url);
callback({});
});
```
### Source Maps
Ensure source maps are enabled for better debugging:
```ts
// tsconfig.json
{
"compilerOptions": {
"sourceMap": true,
"inlineSourceMap": false,
"inlineSources": true
}
}
```
## Systematic Debugging Approach
```ts
// 1. Reproduce the issue consistently
// 2. Isolate the problem (main vs webview)
// 3. Add logging around suspected code
// 4. Use breakpoints in DevTools/debugger
// 5. Check error messages and stack traces
// 6. Review recent changes (git diff)
// 7. Test in isolation (minimal reproduction)
// 8. Check documentation and examples
// 9. Search issues on GitHub
// 10. Ask on Discord
// Debugging template
async function debugIssue() {
logger.info("=== Debug Session Started ===");
logger.info("Environment:", {
platform: process.platform,
version: app.getVersion(),
development: process.env.NODE_ENV === "development",
});
try {
logger.info("Step 1: Initialize");
// ...
logger.info("Step 2: Execute");
// ...
logger.info("Step 3: Verify");
// ...
logger.info("=== Debug Session Complete ===");
} catch (error) {
logger.error("=== Debug Session Failed ===", error);
throw error;
}
}
```
## Resources
For more on Electrobun:
- **Core skill**: `electrobun` - Basic setup
- **RPC patterns**: `electrobun-rpc-patterns` - RPC debugging
- **Distribution**: `electrobun-distribution` - Build issues
- **GitHub Issues**: https://github.com/blackboardsh/electrobun/issues
- **Discord**: https://discord.gg/ueKE4tjaCE