Eugeny/tabby · error · Error

Vault is locked

Error message

Vault is locked

What it means

Thrown by the VaultFileProvider's `selectAndStoreFile` when `vault.load()` returns null, which happens when the vault store is unset (`VaultService.store === null`) - i.e. the vault feature is disabled or no StoredVault has been created yet. The provider refuses to store a file because there is nowhere secure to put it.

Source

Thrown at tabby-core/src/services/vault.service.ts:283

    prefix = 'vault://'

    constructor (
        private vault: VaultService,
        private platform: PlatformService,
        private selector: SelectorService,
        private zone: NgZone,
    ) {
        super()
    }

    async isAvailable (): Promise<boolean> {
        return this.vault.isEnabled()
    }

    async selectAndStoreFile (description: string): Promise<string> {
        const vault = await this.vault.load()
        if (!vault) {
            throw new Error('Vault is locked')
        }
        const files = vault.secrets.filter(x => x.type === VAULT_SECRET_TYPE_FILE) as VaultFileSecret[]
        if (files.length) {
            const result = await this.selector.show<VaultFileSecret|null>('Select file', [
                {
                    name: 'Add a new file',
                    icon: 'fas fa-plus',
                    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}`
            }

View on GitHub (pinned to 14e2d60b9b)

Solutions

  1. Always go through `FileProvidersService.selectProvider()` (or `selectAndStoreFile`) so availability is checked and the user is prompted to set a passphrase.
  2. Before calling VaultFileProvider directly, guard with `if (!await vaultProvider.isAvailable()) { await vault.setEnabled(true, passphrase) }`.
  3. Re-enable the vault: `vault.setEnabled(true, passphrase)` creates the StoredVault, after which `load()` returns a Vault.
  4. Catch the error and fall back to an alternative provider (e.g. ElectronFileProvider) when the vault is unavailable.

Example fix

// before
async selectAndStoreFile (description: string): Promise<string> {
    const vault = await this.vault.load()
    if (!vault) throw new Error('Vault is locked')
    ...
}

// after - ensure availability and fall back gracefully
async selectAndStoreFile (description: string): Promise<string> {
    let vault = await this.vault.load()
    if (!vault) {
        if (!this.vault.isEnabled()) await this.vault.setEnabled(true, await promptPassphrase())
        vault = await this.vault.load()
    }
    if (!vault) throw new Error('Vault is locked')
    ...
Defensive patterns

Strategy: validation

Validate before calling

async function ensureVaultUnlocked (vault: VaultService): Promise<Vault> {
    let v = await vault.load()
    if (!v) {
        if (!vault.isEnabled()) await vault.setEnabled(true, await promptForPassphrase())
        v = await vault.load()
    }
    if (!v) throw new Error('Vault is locked')
    return v
}

Try / catch

try {
    return await vaultProvider.selectAndStoreFile(description)
} catch (e) {
    if (e instanceof Error && e.message === 'Vault is locked') {
        await vault.setEnabled(true, await promptForPassphrase())
        return await vaultProvider.selectAndStoreFile(description)
    }
    throw e
}

Prevention

When it happens

Trigger: Calling `selectAndStoreFile` on VaultFileProvider while `VaultService.isEnabled()` is false OR `store` is null. Note `isAvailable()` returns `vault.isEnabled()`, so this is reachable when a caller invokes the provider directly bypassing `selectProvider`, or when the vault becomes disabled between the availability check and the call.

Common situations: User disabled the vault after a provider was selected; a code path calls VaultFileProvider directly instead of going through FileProvidersService.selectProvider; race where the vault is locked/disabled mid-session.

Related errors


AI-assisted analysis of Eugeny/tabby@14e2d60b9b (2026-08-12). Data as JSON: /api/errors/95b2f96c5662888f. Report an issue: GitHub.