Skip to content

fix: show passphrase dialog for newly added SSH hosts#48

Merged
Keith-CY merged 1 commit intodevelopfrom
fix/ssh-passphrase-skip-second-host
Mar 3, 2026
Merged

fix: show passphrase dialog for newly added SSH hosts#48
Keith-CY merged 1 commit intodevelopfrom
fix/ssh-passphrase-skip-second-host

Conversation

@dev01lay2
Copy link
Copy Markdown
Collaborator

Problem

When adding a second VPS (e.g. ssh:hetzner-2), the passphrase dialog was not shown. Instead the error immediately displayed:

SSH authentication failed (host: ssh:hetzner-2). Passphrase was submitted, but the remote host still rejected it.

No passphrase was ever actually submitted or prompted for.

Root Cause

In connectWithPassphraseFallback (App.tsx), the guard was:

if (host && host.authMethod !== "password" && SSH_PASSPHRASE_RETRY_HINT.test(raw))

When InstallHub.tsx adds a new host, it calls upsertSshHost() then immediately connectRemoteHost(saved.id). But the React sshHosts state hasn't re-rendered yet, so sshHosts.find(h => h.id === hostId) returns undefined.

With host being undefined, the guard short-circuits to false, the passphrase dialog is skipped, and the code falls through to buildSshPassphraseConnectErrorMessage which shows the misleading "Passphrase was submitted" message.

Not a passphrase caching issue — each connection in SshConnectionPool stores its passphrase independently by host ID and never reuses another host's passphrase.

Fix

  1. Guard fix: Change host && to (!host || ...) so the passphrase dialog is shown even when the host isn't in React state yet (assume non-password auth for unknown hosts)
  2. Error message fix: Add passphraseWasSubmitted flag to buildSshPassphraseConnectErrorMessage to distinguish:
    • Passphrase was entered but still rejected → ssh.publicKeyRejected (existing)
    • No passphrase was ever entered → ssh.publicKeyAuthFailed (new, no misleading text)
  3. Locale: Added ssh.publicKeyAuthFailed in both en.json and zh.json
  4. Tests: Updated to cover both paths

Files Changed

  • src/App.tsx — guard fix + pass flag to error builder
  • src/lib/sshConnectErrors.ts — add optional passphraseWasSubmitted param
  • src/locales/en.json / src/locales/zh.json — new locale key
  • src/lib/__tests__/sshConnectErrors.test.ts — test both paths

When adding a second VPS, connectWithPassphraseFallback skipped the
passphrase dialog because the host was not yet in React sshHosts state
(upsertSshHost was called but state hadn't refreshed). The guard
`host && host.authMethod !== 'password'` short-circuited when host
was undefined, falling through to buildSshPassphraseConnectErrorMessage
which misleadingly reported 'Passphrase was submitted'.

Changes:
- Change guard to `(!host || host.authMethod !== 'password')` so
  the passphrase dialog shows even when the host isn't in state yet
- Add passphraseWasSubmitted flag to buildSshPassphraseConnectErrorMessage
  to distinguish 'passphrase entered but rejected' from 'no passphrase
  was ever entered'
- Add new locale key ssh.publicKeyAuthFailed for the no-passphrase case
- Update tests to cover both paths
Copy link
Copy Markdown
Collaborator

@Keith-CY Keith-CY left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — fix is sound. It correctly handles transient missing state when adding a new SSH host and improves SSH failure messaging with an explicit no-passphrase path. No blocking issues found.

Copy link
Copy Markdown
Collaborator

@Keith-CY Keith-CY left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM — fix is sound. It correctly handles transient missing sshHosts state when adding a new SSH host and improves SSH failure messaging with an explicit no-passphrase path. No blocking issues found.

@Keith-CY Keith-CY merged commit f128581 into develop Mar 3, 2026
3 checks passed
@Keith-CY Keith-CY deleted the fix/ssh-passphrase-skip-second-host branch March 3, 2026 03:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants