Eugeny/tabby · warning · Error
Nothing selected
Error message
Nothing selected
What it means
Thrown by VaultFileProvider.addNewFile when `platform.startUpload()` returns an empty transfers array - i.e. the user dismissed the file picker or selected nothing. There is no file content to store, so the operation cannot proceed.
Source
Thrown at tabby-core/src/services/vault.service.ts:309
result: null,
},
...files.map(f => ({
name: f.key.description,
icon: 'fas fa-file',
result: f,
})),
]).catch(() => null)
if (result) {
return `${this.prefix}${result.key.id}`
}
}
return this.addNewFile(description)
}
async addNewFile (description: string): Promise<string> {
const transfers = await this.platform.startUpload()
if (!transfers.length) {
throw new Error('Nothing selected')
}
const transfer = transfers[0]
const id = (await wrapPromise(this.zone, promisify(crypto.randomBytes)(32))).toString('hex')
await this.vault.addSecret({
type: VAULT_SECRET_TYPE_FILE,
key: {
id,
description: `${description} (${transfer.getName()})`,
},
value: Buffer.from(await transfer.readAll()).toString('base64'),
})
return `${this.prefix}${id}`
}
async retrieveFile (key: string): Promise<Buffer> {
if (!key.startsWith(this.prefix)) {
throw new Error('Incorrect type')
}View on GitHub (pinned to 14e2d60b9b)
Solutions
- Treat this as a user cancel: catch the error in the calling flow and abort the import silently (no error toast).
- Confirm the host platform implements `startUpload` (Electron does via dialog; web/headless may not).
- If the picker should not be cancellable, disable the cancel button in the dialog options passed to `startUpload`.
- Differentiate 'Nothing selected' from real failures by inspecting the error message in the caller.
Example fix
// before
const transfers = await this.platform.startUpload()
if (!transfers.length) throw new Error('Nothing selected')
// after - distinguish user cancel from platform failure and surface accordingly
const transfers = await this.platform.startUpload()
if (!transfers.length) {
throw new Error('Nothing selected') // caller maps this to a silent abort
}
// caller:
try { await provider.selectAndStoreFile('Private key') }
catch (e) { if (!/Nothing selected/.test(e.message)) throw e } Defensive patterns
Strategy: try-catch
Validate before calling
async function pickFileOrAbort (platform: PlatformService): Promise<Transfer[]> {
const transfers = await platform.startUpload()
if (!transfers.length) throw new Error('Nothing selected')
return transfers
} Try / catch
try {
return await provider.selectAndStoreFile('Private key')
} catch (e) {
if (e instanceof Error && e.message === 'Nothing selected') return null // user cancel
throw e
} Prevention
- Treat 'Nothing selected' as a benign cancel; never auto-retry.
- Confirm the host implements startUpload before relying on it (Electron does; others may not).
- Pre-validate that a picker is appropriate (i.e. there is something to pick) before launching.
- Differentiate cancel from real platform errors by message matching.
When it happens
Trigger: After the user picks 'Add a new file' (or no existing files exist to choose from), `startUpload()` opens a native picker; if the user cancels it or selects zero files, `transfers.length === 0` and this throws.
Common situations: User cancels the OS file-open dialog while importing a private key or other secret; the picker failed to launch (permissions/manifest issue) and returned empty; a non-Electron platform where `startUpload` is a stub returning [].
Related errors
AI-assisted analysis of Eugeny/tabby@14e2d60b9b (2026-08-12).
Data as JSON: /api/errors/67a0a8fa84e6daa1.
Report an issue: GitHub.