Eugeny/tabby · error · Error
Unsupported vault format version ${vault.version}
Error message
Unsupported vault format version ${vault.version} What it means
Thrown by `decryptVault` when the stored vault's `version` field is anything other than `1` (the only version `encryptVault` writes today). It is a forward/backward-compatibility gate: an unrecognized version cannot be safely parsed because the on-disk layout (salt/iv/contents encoding, cipher params) may differ.
Source
Thrown at tabby-core/src/services/vault.service.ts:84
const keySalt = await promisify(crypto.randomBytes)(PBKDF_SALT_LENGTH)
const iv = await promisify(crypto.randomBytes)(CRYPT_IV_LENGTH)
const key = await deriveVaultKey(passphrase, keySalt)
const plaintext = JSON.stringify(content)
const cipher = crypto.createCipheriv(CRYPT_ALG, key, iv)
const encrypted = Buffer.concat([cipher.update(plaintext, 'utf-8'), cipher.final()])
return {
version: 1,
contents: encrypted.toString('base64'),
keySalt: keySalt.toString('hex'),
iv: iv.toString('hex'),
}
}
async function decryptVault (vault: StoredVault, passphrase: string): Promise<Vault> {
if (vault.version !== 1) {
throw new Error(`Unsupported vault format version ${vault.version}`)
}
const keySalt = Buffer.from(vault.keySalt, 'hex')
const key = await deriveVaultKey(passphrase, keySalt)
const iv = Buffer.from(vault.iv, 'hex')
const encrypted = Buffer.from(vault.contents, 'base64')
const decipher = crypto.createDecipheriv(CRYPT_ALG, key, iv)
const plaintext = decipher.update(encrypted, undefined, 'utf-8') + decipher.final('utf-8')
return migrateVaultContent(JSON.parse(plaintext))
}
export const VAULT_SECRET_TYPE_FILE = 'file'
// Don't make it accessible through VaultService fields
let _rememberedPassphrase: string|null = null
@Injectable({ providedIn: 'root' })
export class VaultService {View on GitHub (pinned to 14e2d60b9b)
Solutions
- Upgrade Tabby to a version that supports the vault version indicated in the error (the number in the message tells you which version you need).
- If you intentionally downgraded and accept data loss, disable the vault and re-create it: call `vault.setEnabled(false)` then `setEnabled(true, newPassphrase)` to write a fresh v1 vault.
- Restore the config file from backup to a v1 vault if a migration corrupted it.
- Avoid mixing Tabby versions across machines that share config-sync; pin all peers to the same release.
Example fix
// before
async function decryptVault (vault: StoredVault, passphrase: string): Promise<Vault> {
if (vault.version !== 1) throw new Error(`Unsupported vault format version ${vault.version}`)
...
}
// after - route known versions to handlers, fail clearly on unknown
async function decryptVault (vault: StoredVault, passphrase: string): Promise<Vault> {
const handlers: Record<number, (v: StoredVault, p: string) => Promise<Vault>> = { 1: decryptVaultV1 }
const handler = handlers[vault.version]
if (!handler) throw new Error(`Unsupported vault format version ${vault.version}; current build supports ${Object.keys(handlers).join(', ')}`)
return handler(vault, passphrase)
} Defensive patterns
Strategy: validation
Validate before calling
const SUPPORTED_VAULT_VERSIONS = new Set([1])
function isVaultVersionSupported (vault: StoredVault): boolean {
return SUPPORTED_VAULT_VERSIONS.has(vault.version)
}
if (!isVaultVersionSupported(stored)) {
throw new Error(`Vault version ${stored.version} unsupported; upgrade Tabby (supports ${[...SUPPORTED_VAULT_VERSIONS].join(',')})`)
} Type guard
function isStoredVault (v: unknown): v is StoredVault {
return typeof v === 'object' && v !== null &&
typeof (v as any).version === 'number' &&
typeof (v as any).contents === 'string' &&
typeof (v as any).keySalt === 'string' &&
typeof (v as any).iv === 'string'
} Try / catch
try {
return await vault.decrypt(stored, passphrase)
} catch (e) {
if (e instanceof Error && /Unsupported vault format version/.test(e.message)) {
// offer to reset vault (data loss) or instruct upgrade
if (await userConfirmsReset()) { await vault.setEnabled(false); await vault.setEnabled(true, passphrase) }
return
}
throw e
} Prevention
- Pin all machines that share config-sync to the same Tabby version.
- Back up the config file before upgrading Tabby.
- Never hand-edit the version field of a stored vault.
- Surface the supported version range in the error so users know what to install.
When it happens
Trigger: Loading a `StoredVault` whose `version` was set by a newer Tabby build (e.g. version 2 after a format change), manually edited, or corrupted (version coerced to a non-number). Also reachable if a future migration writes a new version and an older binary reads it.
Common situations: Downgrading Tabby after a newer version upgraded the vault format; corrupted or hand-edited config file; a config-sync pull from a machine running a newer Tabby that wrote a v2 vault.
Related errors
AI-assisted analysis of Eugeny/tabby@14e2d60b9b (2026-08-12).
Data as JSON: /api/errors/21e7e2a33ba17a06.
Report an issue: GitHub.