Last active
February 17, 2026 13:42
-
-
Save huntie/1c59c208b4fc0e36a457432f208c93c1 to your computer and use it in GitHub Desktop.
Repro for Electron crash on new tab button in macOS Tab Overview https://github.com/electron/electron/issues/49819
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <!DOCTYPE html> | |
| <html> | |
| <head> | |
| <meta charset="UTF-8"> | |
| <title>Tab Overview Crash Test</title> | |
| <style> | |
| body { | |
| font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; | |
| padding: 40px; | |
| background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); | |
| color: white; | |
| margin: 0; | |
| height: 100vh; | |
| display: flex; | |
| flex-direction: column; | |
| justify-content: center; | |
| align-items: center; | |
| } | |
| h1 { | |
| margin: 0 0 10px 0; | |
| font-size: 32px; | |
| } | |
| .subtitle { | |
| margin: 0 0 30px 0; | |
| opacity: 0.9; | |
| font-size: 18px; | |
| } | |
| .instructions { | |
| background: rgba(255, 255, 255, 0.1); | |
| padding: 30px; | |
| border-radius: 12px; | |
| max-width: 600px; | |
| backdrop-filter: blur(10px); | |
| } | |
| .instructions ol { | |
| text-align: left; | |
| line-height: 1.8; | |
| padding-left: 20px; | |
| } | |
| .instructions li { | |
| margin-bottom: 12px; | |
| } | |
| code { | |
| background: rgba(0, 0, 0, 0.3); | |
| padding: 3px 8px; | |
| border-radius: 4px; | |
| font-family: 'SF Mono', Monaco, monospace; | |
| font-size: 14px; | |
| } | |
| .warning { | |
| background: rgba(255, 0, 0, 0.2); | |
| border-left: 4px solid #ff4444; | |
| padding: 15px; | |
| margin-top: 20px; | |
| border-radius: 4px; | |
| } | |
| .success { | |
| background: rgba(0, 255, 0, 0.2); | |
| border-left: 4px solid #44ff44; | |
| padding: 15px; | |
| margin-top: 20px; | |
| border-radius: 4px; | |
| } | |
| </style> | |
| </head> | |
| <body> | |
| <h1>⚠️ Tab Overview Crash Test</h1> | |
| <p class="subtitle">Reproduction for Electron Tab Overview bug</p> | |
| <div class="instructions"> | |
| <p><strong>Steps to reproduce the crash:</strong></p> | |
| <ol> | |
| <li>Go to <strong>View > Show Tab Bar</strong> to show the tab strip</li> | |
| <li>Click the <strong>"+"</strong> button in the tab bar<br> | |
| <em>✅ This is a no-op (does not crash)</em></li> | |
| <li>Go to <strong>View > Show Tab Overview</strong> | |
| <li>Click the <strong>"+ New Tab"</strong> button<br> | |
| <em>❌ App crashes immediately</em></li> | |
| </ol> | |
| <div class="warning"> | |
| <strong>❌ What crashes:</strong> | |
| <ul style="margin: 10px 0 0 0; padding-left: 20px;"> | |
| <li>Clicking "+ New Tab" from Tab Overview</li> | |
| </ul> | |
| <p style="margin: 10px 0 0 0; font-size: 13px; opacity: 0.9;"> | |
| Error: <code>NSLayoutConstraint</code> exception | |
| </p> | |
| </div> | |
| <div class="success"> | |
| <strong>✅ What works (no crash):</strong> | |
| <ul style="margin: 10px 0 0 0; padding-left: 20px;"> | |
| <li>Clicking "+" in the tab bar (no-op)</li> | |
| <li><code>Cmd+T</code> with event handler enabled</li> | |
| </ul> | |
| </div> | |
| </div> | |
| </body> | |
| </html> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const {app, BrowserWindow, Menu} = require('electron'); | |
| const path = require('path'); | |
| // Set to true to test if a handler prevents the crash (spoiler: it doesn't) | |
| const ENABLE_TAB_HANDLER = false; | |
| function createWindow() { | |
| const mainWindow = new BrowserWindow({ | |
| width: 1200, | |
| height: 800, | |
| // Enable tabs for this window (macOS 10.12+) | |
| tabbingIdentifier: 'main', | |
| }); | |
| mainWindow.loadFile(path.join(__dirname, 'index.html')); | |
| // Auto-hide the menu bar on Windows/Linux | |
| mainWindow.setMenuBarVisibility(false); | |
| } | |
| function configureAppMenu() { | |
| const template = [ | |
| ...(process.platform === 'darwin' ? [{role: 'appMenu'}] : []), | |
| {role: 'fileMenu'}, | |
| {role: 'editMenu'}, | |
| {role: 'viewMenu'}, | |
| {role: 'windowMenu'}, | |
| ]; | |
| const menu = Menu.buildFromTemplate(template); | |
| Menu.setApplicationMenu(menu); | |
| } | |
| app.whenReady().then(() => { | |
| createWindow(); | |
| configureAppMenu(); | |
| if (ENABLE_TAB_HANDLER) { | |
| // Even with this handler, clicking "+ New Tab" in Tab Overview crashes | |
| app.on('new-window-for-tab', () => { | |
| console.log('new-window-for-tab event fired'); | |
| const newWindow = new BrowserWindow({ | |
| width: 1200, | |
| height: 600, | |
| tabbingIdentifier: 'main', | |
| }); | |
| newWindow.setMenuBarVisibility(false); | |
| newWindow.loadFile(path.join(__dirname, 'index.html')); | |
| }); | |
| } | |
| app.on( | |
| 'second-instance', | |
| (event, electronArgv, workingDirectory, additionalData) => { | |
| // Handle second instance if needed | |
| }, | |
| ); | |
| app.on('activate', () => { | |
| if (BrowserWindow.getAllWindows().length === 0) { | |
| createWindow(); | |
| } | |
| }); | |
| }); | |
| app.on('window-all-closed', () => { | |
| app.quit(); | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| { | |
| "name": "unaccountable-burst-doubt-eh3g7", | |
| "productName": "unaccountable-burst-doubt-eh3g7", | |
| "description": "My Electron application description", | |
| "keywords": [], | |
| "main": "./main.js", | |
| "version": "1.0.0", | |
| "author": "huntie", | |
| "scripts": { | |
| "start": "electron ." | |
| }, | |
| "dependencies": {}, | |
| "devDependencies": { | |
| "electron": "40.1.0" | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * The preload script runs before `index.html` is loaded | |
| * in the renderer. It has access to web APIs as well as | |
| * Electron's renderer process modules and some polyfilled | |
| * Node.js functions. | |
| * | |
| * https://www.electronjs.org/docs/latest/tutorial/sandbox | |
| */ | |
| window.addEventListener('DOMContentLoaded', () => { | |
| const replaceText = (selector, text) => { | |
| const element = document.getElementById(selector) | |
| if (element) element.innerText = text | |
| } | |
| for (const type of ['chrome', 'node', 'electron']) { | |
| replaceText(`${type}-version`, process.versions[type]) | |
| } | |
| }) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /** | |
| * This file is loaded via the <script> tag in the index.html file and will | |
| * be executed in the renderer process for that window. No Node.js APIs are | |
| * available in this process because `nodeIntegration` is turned off and | |
| * `contextIsolation` is turned on. Use the contextBridge API in `preload.js` | |
| * to expose Node.js functionality from the main process. | |
| */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment