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

  1. Catch the error in the caller and treat 'canceled' as a benign user abort (no toast, just stop the flow).
  2. If mocking in tests, stub `electron.dialog.showOpenDialog` to resolve with a chosen filePaths array.
  3. Pre-validate that a file path is expected before opening the dialog to reduce accidental cancels.
  4. 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

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.