Eugeny/tabby · info · Error
canceled
Error message
canceled
What it means
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.
Source
Thrown at tabby-electron/src/services/fileProvider.service.ts:27
name = 'Filesystem'
constructor (
private electron: ElectronService,
private hostWindow: ElectronHostWindow,
) {
super()
}
async selectAndStoreFile (description: string): Promise<string> {
const result = await this.electron.dialog.showOpenDialog(
this.hostWindow.getWindow(),
{
buttonLabel: `Select ${description}`,
properties: ['openFile', 'treatPackageAsDirectory'],
},
)
if (result.canceled || !result.filePaths.length) {
throw new Error('canceled')
}
return `file://${result.filePaths[0]}`
}
async retrieveFile (key: string): Promise<Buffer> {
if (key.startsWith('file://')) {
key = key.substring('file://'.length)
} else if (key.includes('://')) {
throw new Error('Incorrect type')
}
return fs.readFile(key, { encoding: null })
}
}
View on GitHub (pinned to 14e2d60b9b)
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.
Example fix
// before
if (result.canceled || !result.filePaths.length) throw new Error('canceled')
// caller pattern
try { key = await fileProvider.selectAndStoreFile('Private key') }
catch (e) { if (e.message === 'canceled') return; throw e } Defensive patterns
Strategy: try-catch
Try / catch
try {
key = await electronProvider.selectAndStoreFile('Select file')
} catch (e) {
if (e instanceof Error && e.message === 'canceled') return // user dismissed dialog
throw e
} Prevention
- 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.
When it happens
Trigger: 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).
Common situations: 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.
Related errors
AI-assisted analysis of Eugeny/tabby@14e2d60b9b (2026-08-12).
Data as JSON: /api/errors/765e5391605eb58d.
Report an issue: GitHub.