electrobun-debugging
Electrobun Debugging
Comprehensive debugging and troubleshooting guide for Electrobun applications.
Development Environment
Basic Development Setup
# 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:
# 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
// 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
# 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
// 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
// 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
// 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
// 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
// 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
// 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
// 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:
// 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
// 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:
// 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'"
# Solution: Install dependencies
bun install
# Verify electrobun is installed
bun pm ls electrobun
Issue: Native module compilation fails
# 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)
# Install WebView2 Runtime
# Download from microsoft.com/edge/webview2
Runtime Errors
Issue: Window not showing
// 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
// 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
// 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:
// Issue: App won't open (Gatekeeper)
// Solution: Code sign and notarize
// Issue: Permissions denied
// Solution: Add Info.plist entries
<key>NSCameraUsageDescription</key>
<string>App needs camera access</string>
<key>NSMicrophoneUsageDescription</key>
<string>App needs microphone access</string>
Windows:
// Issue: SmartScreen warning
// Solution: Code sign with trusted certificate
// Issue: Antivirus blocking
// Solution: Code sign and submit to vendors
Linux:
// 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
// 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:
// tsconfig.json
{
"compilerOptions": {
"sourceMap": true,
"inlineSourceMap": false,
"inlineSources": true
}
}
Systematic Debugging Approach
// 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
More from rajavijayach/electrobun-skills
electrobun-window-management
Advanced window and view management patterns for Electrobun desktop applications. This skill covers multi-window architectures, BrowserView for embedded webviews, window lifecycle management, window orchestration, tab systems, and complex window hierarchies. Use this skill when building applications with multiple windows, implementing browser-like tab interfaces, managing parent-child window relationships, creating floating panels or toolbars, implementing picture-in-picture modes, managing window state persistence across sessions, or building applications that require sophisticated window coordination. Triggers include "multiple windows", "tab system", "BrowserView", "window orchestration", "floating window", "child window", "window state", "window manager", "multi-window app", or discussions about complex window management in Electrobun desktop applications.
62electrobun-native-ui
Native UI integration for Electrobun desktop applications including ApplicationMenu, ContextMenu, system Tray, native dialogs, keyboard shortcuts, and platform-specific UI patterns. This skill covers creating application menus with submenus and accelerators, context menus triggered by right-click, system tray icons with menus, file/folder dialogs, message boxes, notification systems, global keyboard shortcuts, menu item roles, dynamic menu updates, platform-specific menu conventions (macOS menu bar, Windows system menu), drag-and-drop integration, and native theming. Use when implementing application menus, adding system tray functionality, creating context menus, showing file pickers, implementing keyboard shortcuts, displaying notifications or dialogs, or building platform-native UI experiences. Triggers include "menu", "tray icon", "context menu", "file dialog", "shortcuts", "accelerator", "native dialog", "system tray", "notification", "menu bar", or "right-click menu".
61electrobun-distribution
Packaging, code signing, notarization, and distribution for Electrobun desktop applications. This skill covers building production bundles, creating installers and distributable packages, code signing for Windows and macOS, Apple notarization for Gatekeeper, auto-updater implementation, delta updates, update servers, cross-platform build processes, CI/CD integration, app icons and resources, version management, release workflows, Windows SmartScreen requirements, macOS DMG creation, Linux package formats (deb, rpm, AppImage), and distribution best practices. Use when preparing app for production, implementing auto-updates, setting up code signing certificates, troubleshooting distribution issues, creating installers, configuring update servers, building for multiple platforms, or releasing new versions. Triggers include "build", "package", "distribute", "code sign", "notarize", "installer", "auto-update", "release", "production build", "DMG", "updater", "delta update", or "certificate".
51electrobun-rpc-patterns
Advanced type-safe RPC patterns for Electrobun desktop applications. Covers bidirectional main↔webview communication, type safety with TypeScript, error handling and validation, performance optimization, streaming data patterns, batch operations, retry strategies, event-based communication, shared type definitions, RPC middleware, request/response patterns, and complex data synchronization. Use this skill when implementing complex communication between main and webview processes, need type-safe RPC with full IntelliSense, handling large data transfers, implementing real-time updates, building type-safe APIs between processes, debugging RPC issues, optimizing RPC performance, or implementing advanced patterns like streaming, batching, or pub/sub. Triggers include "RPC", "main webview communication", "type-safe RPC", "bidirectional RPC", "RPC performance", "RPC error handling", "shared types", "process communication", or "IPC patterns".
50