{"record":{"id":"667066e24265ec25","repo":"Eugeny/tabby","slug":"not-found","errorCode":null,"errorMessage":"Not found","messagePattern":"Not found","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"tabby-core/src/services/fileProviders.service.ts","lineNumber":29,"sourceCode":"        private translate: TranslateService,\n        @Inject(FileProvider) private fileProviders: FileProvider[],\n    ) { }\n\n    async selectAndStoreFile (description: string): Promise<string> {\n        return this.selectProvider().then(p => {\n            return p.selectAndStoreFile(description)\n        })\n    }\n\n    async retrieveFile (key: string): Promise<Buffer> {\n        for (const p of this.fileProviders) {\n            try {\n                return await p.retrieveFile(key)\n            } catch {\n                continue\n            }\n        }\n        throw new Error('Not found')\n    }\n\n    async selectProvider (): Promise<FileProvider> {\n        const providers: FileProvider[] = []\n        await Promise.all(this.fileProviders.map(async p => {\n            if (await p.isAvailable()) {\n                providers.push(p)\n            }\n        }))\n        if (!providers.length) {\n            this.notifications.error(this.translate.instant('Vault master passphrase needs to be set to allow storing secrets'))\n            throw new Error('No available file providers')\n        }\n        if (providers.length === 1) {\n            return providers[0]\n        }\n        return this.selector.show(\n            this.translate.instant('Select file storage'),","sourceCodeStart":11,"sourceCodeEnd":47,"githubUrl":"https://github.com/Eugeny/tabby/blob/14e2d60b9b6dee84a53c37f05eefeb803787de04/tabby-core/src/services/fileProviders.service.ts#L11-L47","documentation":"Thrown by `FileProvidersService.retrieveFile` after it has iterated every registered FileProvider and each one either threw or had no match for the given key. It is the catch-all 'no provider could resolve this key' failure. The message is intentionally generic because the specific failure is provider-internal and swallowed.","triggerScenarios":"Calling `retrieveFile(key)` where `key` is unknown to all providers, has been deleted from the vault, references a file:// path that no longer exists on disk, or whose provider (vault/electron) is locked/unavailable so each provider rejects.","commonSituations":"A profile references a private-key file that was removed from the vault or whose source file was deleted; a config synced from another machine whose stored file key is local to that machine; vault locked so VaultFileProvider throws 'Vault is locked' and ElectronFileProvider throws 'Incorrect type'.","solutions":["Check the key format: vault keys are prefixed (e.g. `vault:`), electron keys are `file://...` - confirm the key matches an existing entry.","Ensure the vault is unlocked before retrieval (call `vault.load()` / unlock modal) so VaultFileProvider can return the secret.","If the underlying file was deleted, re-import it via `selectAndStoreFile` to obtain a fresh key and update the referencing profile/config.","Log per-provider errors (replace `catch { continue }` with `catch(e) { lastError = e; continue }`) to surface the real cause instead of the generic 'Not found'."],"exampleFix":"// before\nasync retrieveFile (key: string): Promise<Buffer> {\n    for (const p of this.fileProviders) {\n        try { return await p.retrieveFile(key) }\n        catch { continue }\n    }\n    throw new Error('Not found')\n}\n\n// after - capture the last error for diagnostics\nasync retrieveFile (key: string): Promise<Buffer> {\n    let lastErr: unknown\n    for (const p of this.fileProviders) {\n        try { return await p.retrieveFile(key) }\n        catch (e) { lastErr = e; continue }\n    }\n    throw new Error(`Not found: ${key} (last provider error: ${lastErr})`)\n}","handlingStrategy":"try-catch","validationCode":"async function fileExistsSomewhere (providers: FileProvider[], key: string): Promise<boolean> {\n    for (const p of providers) {\n        try { await p.retrieveFile(key); return true } catch { /* try next */ }\n    }\n    return false\n}\n\n// before retrieving\nif (!await fileExistsSomewhere(fileProviders, key)) {\n    throw new Error(`No provider has key ${key}; re-import the file`)\n}","typeGuard":"function isVaultFileKey (key: string): boolean { return key.startsWith('vault:') }\nfunction isElectronFileKey (key: string): boolean { return key.startsWith('file://') }","tryCatchPattern":"try {\n    return await fileProviders.retrieveFile(key)\n} catch (e) {\n    if (e instanceof Error && e.message === 'Not found') {\n        // prompt user to re-import; do not crash the consuming flow\n        return await fileProviders.selectAndStoreFile('Re-import missing file')\n    }\n    throw e\n}","preventionTips":["Keep a registry of stored keys per profile so missing ones are detected before retrieval.","Improve retrieveFile to surface the last provider error instead of a generic 'Not found'.","Unlock the vault before any retrieval-heavy operation to keep VaultFileProvider available.","Validate key prefixes (vault:/file://) against the expected provider before calling."],"tags":["file-providers","vault","retrieval","configuration"],"backgroundTag":null,"analyzedSha":"14e2d60b9b6dee84a53c37f05eefeb803787de04","analyzedAt":"2026-08-12T11:46:48.773Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}