fix(config): a saved password that failed to load connected silently with a blank one (FR-CFG-08) - #202
Merged
Conversation
…with a blank one (FR-CFG-08) Found on DC0SK's live K4 after a host OS migration: the app connected for ~1.5s with zero read-back and disconnected, reproducing on every build back to and including the last release, ruling out a code regression here. Root cause: SecretStore::get returned Option<String>, so "no entry" and "the store itself failed" (locked keyring, D-Bus unreachable, a timed-out read) were the same value, and both call sites collapsed a failed read to an empty password with .ok().flatten().unwrap_or_default() and no warning. SecretStore::get now returns Result<Option<String>, SecretError>, threaded through a new load_secret_timed/password_load_outcome pair, with a warning shown next to the password field whenever a load did not cleanly come back as "found" or "nothing saved". Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
dc0sk
force-pushed
the
fix/silent-empty-saved-password
branch
from
September 22, 2026 18:13
ed057f4 to
11eee4f
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
A saved connection password that fails to load from the OS keychain — a locked
or unreachable keyring, a timed-out read — was silently treated the same as
"no password was ever saved". The app then tried to connect with a blank
password, which the K4 rejects, producing an unexplained connect-and-drop
within about 1.5 s and zero read-back (not even VFO frequency), with nothing
in the UI to say why.
How found
DC0SK migrated the host OS (Manjaro → AerynOS) and hit this on the live K4.
Bisection ruled out a code regression: every build back to and including the
last release (v0.9.0, unmodified) reproduced it, so the actual cause is
environmental (most likely the login keyring not being unlocked/populated on
the new profile) — confirmed by typing the password in manually, which
connects cleanly. But the underlying defect this PR fixes is real and
independent of that: any keychain read failure, on any machine, produces
this same silent, unexplained symptom.
The fix
SecretStore::getnow returnsResult<Option<String>, SecretError>insteadof
Option<String>.Ok(None)means "no secret for this account" (not anerror);
Errmeans the store itself could not be read. The two werepreviously indistinguishable.
App::newat startup,select_peerwhen choosing a keychain-backed cached peer) used to collapse any read
failure with
.ok().flatten().unwrap_or_default(). They now go throughload_secret_timed/password_load_outcome, which keep "no password saved","the store failed", and "the read timed out" as three distinct outcomes.
existing
Cautioncolour) whenever the load did not cleanly come back as"found" or "nothing saved" — visible before you click Connect, instead of
manifesting only as an unexplained failure afterward.
Tests
fr_cfg_08_no_password_saved_is_not_a_warning,..._a_saved_password_loads_with_no_warning,..._a_store_failure_warns_and_names_the_reason,..._a_timeout_warns_distinctly_from_a_failure_or_a_miss— the pure decisionfunction, all four outcomes.
..._wiring_a_failing_store_reads_as_an_error_not_a_miss,..._wiring_a_hung_store_times_out_instead_of_blocking— through the realthread/channel wiring (a hung store is abandoned at the bound, not blocked
on).
fr_cfg_08_a_store_failure_is_not_a_clean_miss(k4-config).every non-clean-hit outcome to
(empty, no warning)) — 2 of 6 tests failed,confirming they catch the actual regression.
Verified
cargo fmt --all -- --check,cargo clippy --workspace --all-targets --all-features,cargo clippy -p k4remote --features kpod --all-targets—all clean.
cargo test --workspace— all green.cargo xtask— 0 R3 gaps,FR-CFG-08traced.Not covered / still yours
migration) — separate from this fix, and outside what a rebuild can
change. Worth checking
secret-tool search service k4remoteorequivalent, and that the login keyring auto-unlocks with your session.
keychain (e.g. temporarily stop
gnome-keyring-daemonand restart witha saved peer selected).