{"record":{"id":"c282f12ac2a492da","repo":"Eugeny/tabby","slug":"passphrase-prompt-cancelled","errorCode":null,"errorMessage":"Passphrase prompt cancelled","messagePattern":"Passphrase prompt cancelled","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"warning","filePath":"tabby-ssh/src/session/ssh.ts","lineNumber":967,"sourceCode":"                    passphrase = await this.passwordStorage.loadPrivateKeyPassword(keyHash)\n                    triedSavedPassphrase = true\n                    continue\n                }\n                if ([\n                    'Error: Keys(KeyIsEncrypted)',\n                    'Error: Keys(SshKey(Ppk(Encrypted)))',\n                    'Error: Keys(SshKey(Ppk(IncorrectMac)))',\n                    'Error: Keys(SshKey(Crypto))',\n                ].includes(e.toString())) {\n                    await this.passwordStorage.deletePrivateKeyPassword(keyHash)\n\n                    const modal = this.ngbModal.open(PromptModalComponent)\n                    modal.componentInstance.prompt = 'Private key passphrase'\n                    modal.componentInstance.password = true\n                    modal.componentInstance.showRememberCheckbox = true\n\n                    const result = await modal.result.catch(() => {\n                        throw new Error('Passphrase prompt cancelled')\n                    })\n\n                    passphrase = result?.value\n                    if (passphrase && result.remember) {\n                        this.passwordStorage.savePrivateKeyPassword(keyHash, passphrase)\n                    }\n                } else {\n                    this.notifications.error('Could not read the private key', e.toString())\n                    throw e\n                }\n            }\n        }\n    }\n\n    ref (): void {\n        this.refCount++\n    }\n","sourceCodeStart":949,"sourceCodeEnd":985,"githubUrl":"https://github.com/Eugeny/tabby/blob/14e2d60b9b6dee84a53c37f05eefeb803787de04/tabby-ssh/src/session/ssh.ts#L949-L985","documentation":"Thrown inside loadPrivateKeyWithPassphraseMaybe() when an encrypted private key needs a passphrase and the user dismisses the PromptModalComponent passphrase dialog (Esc / backdrop / cancel). The modal.result promise rejects on dismissal; the catch rethrows this error to abort key loading.","triggerScenarios":"russh.KeyPair.parse fails with one of 'KeyIsEncrypted', 'Ppk(Encrypted)', 'Ppk(IncorrectMac)', or 'SshKey(Crypto)', the stored passphrase (if any) was already tried and deleted, the passphrase modal is opened, and the user cancels it. modal.result.catch at ssh.ts:966 then throws 'Passphrase prompt cancelled'.","commonSituations":"User hits Escape on the passphrase prompt; clicks outside the modal (backdrop dismiss); switches away and the modal auto-dismisses; automated/headless run where no one is present to answer the modal; a previously-remembered passphrase became wrong (key re-encrypted) and the user cancels the re-prompt.","solutions":["Re-open the key and enter the correct passphrase instead of cancelling.","If running headless, pre-store the passphrase via passwordStorage.savePrivateKeyPassword(keyHash, passphrase) so no modal is needed.","Use an unencrypted key, or decrypt it once with ssh-keygen -p -f <key> so no passphrase is required.","Use an SSH agent (ssh-add) so the key passphrase is handled outside Tabby's modal path.","Ensure the modal is not auto-dismissed by router/background changes during the prompt."],"exampleFix":"// before: encrypted key, user cancels modal -> 'Passphrase prompt cancelled'\n// after: decrypt the key once\n//   ssh-keygen -p -f ~/.ssh/id_ed25519\n// or pre-seed the remembered passphrase in passwordStorage before connecting","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n    await session.loadPrivateKeyWithPassphraseMaybe(key)\n} catch (e) {\n    if (e.message === 'Passphrase prompt cancelled') {\n        // user opted out; abort key auth gracefully\n        return\n    }\n    throw e\n}","preventionTips":["Pre-store the passphrase with passwordStorage.savePrivateKeyPassword so no modal is needed.","Decrypt the key once with ssh-keygen -p to remove the passphrase.","Load keys into ssh-agent to bypass Tabby's passphrase modal entirely.","Avoid running interactive SSH flows headless where the modal cannot be answered."],"tags":["ssh","private-key","passphrase","modal","user-input"],"backgroundTag":null,"analyzedSha":"14e2d60b9b6dee84a53c37f05eefeb803787de04","analyzedAt":"2026-08-12T11:46:48.773Z","schemaVersion":2},"datasetVersion":"2026-08-12T18:17:37.767Z"}