{"record":{"id":"765e5391605eb58d","repo":"Eugeny/tabby","slug":"canceled","errorCode":null,"errorMessage":"canceled","messagePattern":"canceled","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"info","filePath":"tabby-electron/src/services/fileProvider.service.ts","lineNumber":27,"sourceCode":"    name = 'Filesystem'\n\n    constructor (\n        private electron: ElectronService,\n        private hostWindow: ElectronHostWindow,\n    ) {\n        super()\n    }\n\n    async selectAndStoreFile (description: string): Promise<string> {\n        const result = await this.electron.dialog.showOpenDialog(\n            this.hostWindow.getWindow(),\n            {\n                buttonLabel: `Select ${description}`,\n                properties: ['openFile', 'treatPackageAsDirectory'],\n            },\n        )\n        if (result.canceled || !result.filePaths.length) {\n            throw new Error('canceled')\n        }\n\n        return `file://${result.filePaths[0]}`\n    }\n\n    async retrieveFile (key: string): Promise<Buffer> {\n        if (key.startsWith('file://')) {\n            key = key.substring('file://'.length)\n        } else if (key.includes('://')) {\n            throw new Error('Incorrect type')\n        }\n        return fs.readFile(key, { encoding: null })\n    }\n}\n","sourceCodeStart":9,"sourceCodeEnd":42,"githubUrl":"https://github.com/Eugeny/tabby/blob/14e2d60b9b6dee84a53c37f05eefeb803787de04/tabby-electron/src/services/fileProvider.service.ts#L9-L42","documentation":"Thrown by ElectronFileProvider.selectAndStoreFile when the native open dialog returns `canceled: true` or an empty `filePaths` array. The lower-cased 'canceled' is the canonical signal that the user dismissed the picker, used so callers can pattern-match on it.","triggerScenarios":"Calling `selectAndStoreFile` in an Electron host; the user clicks Cancel, presses ESC, or closes the `dialog.showOpenDialog` window. Also thrown if the dialog returns no paths for any reason (rare platform bug).","commonSituations":"User cancels while selecting a private key, color scheme file, or other importable asset; an automated test invokes the provider without mocking the dialog and it returns canceled.","solutions":["Catch the error in the caller and treat 'canceled' as a benign user abort (no toast, just stop the flow).","If mocking in tests, stub `electron.dialog.showOpenDialog` to resolve with a chosen filePaths array.","Pre-validate that a file path is expected before opening the dialog to reduce accidental cancels.","Differentiate from real errors by matching `e.message === 'canceled'` rather than generic catch."],"exampleFix":"// before\nif (result.canceled || !result.filePaths.length) throw new Error('canceled')\n\n// caller pattern\ntry { key = await fileProvider.selectAndStoreFile('Private key') }\ncatch (e) { if (e.message === 'canceled') return; throw e }","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    key = await electronProvider.selectAndStoreFile('Select file')\n} catch (e) {\n    if (e instanceof Error && e.message === 'canceled') return  // user dismissed dialog\n    throw e\n}","preventionTips":["Always treat 'canceled' as a benign user action and abort the calling flow silently.","In tests, mock electron.dialog.showOpenDialog to return a chosen path.","Do not retry automatically on cancel; the user explicitly opted out.","Match on the exact message string 'canceled' to distinguish from real failures."],"tags":["electron","file-providers","user-cancel","dialog","platform"],"backgroundTag":null,"analyzedSha":"14e2d60b9b6dee84a53c37f05eefeb803787de04","analyzedAt":"2026-08-12T11:46:48.773Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}