Created attachment 194006 [details] Forensic snapshot and full investigation report inside it DESCRIPTION After approximately 11 hours of uptime, kwalletd6's anonymous RSS grew from a normal baseline (~50 MB) to roughly 18.9 GB (anon-rss: 19,796,084 kB), exhausting the system's 32 GB of physical RAM plus 4 GB of swap. The Linux kernel OOM killer terminated kwalletd6 (PID 3911). systemd restarted it immediately and the system recovered. The restarted instance logs GTask "finalized without ever returning" warnings related to Secret Service prompt handling, suggesting the leak occurs in the D-Bus Secret Service code path. Two attachments are provided with this report: 1. Full investigation report with complete evidence and analysis. 2. Forensic snapshot archive (14 MB compressed) containing OOM logs, complete journal, /proc snapshots, D-Bus traces, and a core dump of the running kwalletd6 instance for analysis. STEPS TO REPRODUCE 1. Leave a KDE Plasma 6 session running with kwalletd6 D-Bus activated, Chrome (or other libsecret-using clients) running in the background. 2. Allow the system to remain idle or in light use for approximately 11+ hours. 3. Observe kwalletd6 RSS growth via system monitor. The leak rate is approximately 28 MB/minute once active. At ~18-19 GB RSS the kernel OOM killer will terminate kwalletd6. Note: The issue is not fully reproducible on demand. See full report for conditions observed. OBSERVED RESULT - kwalletd6 anon-rss: 19,796,084 kB (~18.9 GB) at OOM kill time. - file-rss: only 2,212 kB (negligible file-backed pages), confirming a pure heap leak, not file cache or shared memory. - VIRT: 23,228,428 kB (~22.2 GB). - systemd reported 18.9G memory peak and 2.9G swap peak. - oom_score_adj: 200 (positive adjustment set by systemd for the dbus-activated unit). - After OOM kill, the restarted kwalletd6 (PID 172592) logged: - "received unexpected result type ao from Completed signal instead of expected o" - "GTask secret_service_real_prompt_async ... finalized without ever returning (using g_task_return_*()). This potentially indicates a bug in the program." - The OOM-killed instance (PID 3911) did not log these GTask warnings during its 11-hour lifetime, suggesting either a silent leak path or different code path was exercised. EXPECTED RESULT kwalletd6 should maintain a stable memory footprint of approximately 30-100 MB RSS regardless of uptime or Secret Service client activity. SOFTWARE/OS VERSIONS Operating System: Arch Linux (rolling), x86_64 KDE Plasma Version: 6.7.2-1 KDE Frameworks Version: (bundled in kwallet 6.27.0-1) Qt Version: 6.11.1-1 Linux Kernel: 7.0.14-zen1-1-zen Key packages: kwallet: 6.27.0-1 glib2: 2.88.2-1 libsecret: 0.21.7-1 qca-qt6: 2.3.10-7 xdg-desktop-portal: 1.22.1-2 xdg-desktop-portal-kde: 6.7.2-1 ADDITIONAL INFORMATION - systemd-oomd is verified disabled; this was the kernel OOM killer. - Bug 490788 (QCA::Initializer destruction order, fixed in 6.23.0) shares the same code area (KWalletFreedesktopService/KWalletFreedesktopSessionAlgorithmDhAes) but causes a different symptom (crash on shutdown, not memory leak during operation). Our version 6.27.0 includes the fix, so this leak is a separate issue. - Portal registration failure ("Could not register app ID") affects ALL KDE components equally on this installation -- it is systemic, not kwallet-specific, and therefore likely not the root cause. - The signal type mismatch ("ao" vs "o" for the Completed signal) is a key lead: it causes the GLib GTask for the Secret Service prompt to never complete, potentially leaking the allocated task resources. - Chrome (google-chrome 150.0.7871.46) is the most likely frequent caller of the Secret Service API during the observation period, but direct client-side evidence is not available in the current logs. - Two files attached: (1) Forensic snapshot: kwalletd6_forensics_20260704_200709.tar.xz (2) Full investigation report inside the forensic snapshot: kwalletd6_memory_leak_bug_report.txt
Reproduced, with a much faster leak rate, evidence tying it to the kwalletd6 -> ksecretd loop in bug 522307, and confirmation that downgrading pam_kwallet6 (per that bug's bisect) eliminates the problem. SOFTWARE VERSIONS OS: Fedora 44 (KDE spin), kernel 7.0.14-201.fc44.x86_64 Plasma: 6.7.1 (Wayland) kf6-kwallet / kwalletd6: 6.27.0-1.fc44 pam-kwallet (pam_kwallet6): 6.7.1-1.fc44 Secret Service backend: ksecretd OBSERVED - kwalletd6 D-Bus-activated at 10:43:07 after a fresh boot + login (journalctl confirms zero suspend/resume events in the boot). OOM kill at 11:38:01 — so ~55 GB anon RSS in under 55 minutes, roughly 1 GB/min versus the ~28 MB/min in the original report. It exhausted 64 GB RAM plus most of an 8 GB swap. - Kernel OOM record: Out of memory: Killed process 26948 (kwalletd6) total-vm:64172028kB, anon-rss:55416916kB, file-rss:5544kB, shmem-rss:0kB, UID:1000 pgtables:124492kB oom_score_adj:200 - systemd accounting for the unit: dbus-:1.2-org.kde.kwalletd6@0.service: Consumed 14min 11.211s CPU time over 54min 55.588s wall clock time, 53G memory peak, 7.7G memory swap peak. - Same post-restart warnings as the original report: received unexpected result type ao from Completed signal instead of expected o g_task_return_error: assertion 'error != NULL' failed GTask secret_service_real_prompt_async (...) finalized without ever returning - Additional failure face: ~50 minutes after the OOM respawn, the replacement kwalletd6 instance silently deadlocked — 0% CPU but no reply to any D-Bus call (even org.kde.KWallet.wallets timed out after 25 s), so every client (kwalletmanager, kded6 NM secret agent) failed with timeouts. Killing it and letting D-Bus respawn recovered. So the Secret Service client path in kwalletd6 can leak-loop OR deadlock depending on state. - Link to bug 522307: for the entire window that kwalletd6 was growing, ksecretd (--pam-login) was spinning at ~32% CPU; the moment kwalletd6 was killed, ksecretd went fully idle. That report's dbus-monitor capture shows kwalletd6 calling ReadAlias("default") on ksecretd in a tight loop, and its reporter bisected the trigger to pam_kwallet6 6.7.1 — the version installed here. CONFIRMED MITIGATION Downgrading pam-kwallet to 6.6.4-1.fc44 (Fedora carries no 6.7.0) eliminates the issue: after reboot, ksecretd consumes zero CPU (previously ~32% from the first minute of the session) and kwalletd6 RSS stays flat at ~60 MB. This independently confirms the pam_kwallet6 6.7.1 bisect from bug 522307 on a second distribution. Suggest cross-linking the two reports — 522307 (CPU loop) and this one (memory growth) look like two symptoms of the same defect.
I’d like to clarify that the pam-kwallet version on my system is 6.7.2‑1, not 6.7.1. The memory leak is reproducible with this version as well, so the problem is not limited to the version initially mentioned in the bisect. Thanks.
Data point: the leak recurred on my machine with pam-kwallet6 downgraded to 6.6.4 (retracting the mitigation I reported earlier on this bug and bug 522307). Different trigger shape this time - kwalletd6 was D-Bus-activated by a client 65 min after login (not at login), and RSS growth began immediately on activation. Leak rate was far higher than in my original report: each kwalletd6 instance grew from ~60MB to 2.3-4.2GB in ~2-3 minutes (vs ~28MB/min previously), across 6 consecutive dbus-respawned instances (a >2GB watchdog killed each one), and the loop stopped permanently only when a pending Secret Service prompt was cancelled. Full timeline, journal correlates, and the prompt-path analysis in my comment today on bug 522307. Versions at episode time: kf6-kwallet-6.27.0-1.fc44, pam-kwallet-6.6.4-1.fc44, Fedora 44, Plasma Wayland.
(In reply to zosima from comment #3) > the leak recurred on my machine with pam-kwallet6 downgraded to > 6.6.4 (retracting the mitigation I reported earlier). There are no significant code changes in pam-kwallet6 between 6.6.4 and 6.7.x (or even much further back), just version bumps and CI updates. So it wouldn't make sense for a downgrade of it to fix these two bugs. https://invent.kde.org/plasma/kwallet-pam/-/compare/v6.6.4..v6.7.2?from_project_id=2562 https://invent.kde.org/plasma/kwallet-pam/-/network/master?ref_type=heads
*** Bug 522718 has been marked as a duplicate of this bug. ***
Also reproducible on openSUSE Tumbleweed, so this is not distro-specific: openSUSE Tumbleweed, Wayland kwalletd6 6.28.0 plasma6-nm 6.7.2, plasmashell 6.7.2 Qt 6.11.1 dbus-1 1.14.10 kernel 7.1.3 THE WRITE ACTUALLY SUCCEEDS - ONLY ITS COMPLETION IS LOST This seems worth highlighting, because it reframes the bug: it is not that saving the secret fails. After the loop had been running for hours I dumped the wallet directly: $ kwallet-query -l -f "Network Management" kdewallet ... 188 entries ... $ kwallet-query -r "{<uuid>};802-11-wireless-security" -f "Network Management" kdewallet (non-empty, contains the psk key, same structure as entries written before the regression) So the data lands in the wallet correctly. What never arrives is the acknowledgement, which matches the "secret_service_real_prompt_async finalized without ever returning" backtrace and the "ao" vs "o" signature mismatch in the Completed signal. The client therefore never learns it succeeded and retries forever. WHO IS RETRYING A short "dbus-monitor --profile" capture (3 s, ~34k lines) shows kded6 - the plasma-nm secret agent - calling org.kde.KWallet.writePassword (plus open and networkWallet) on kwalletd6 at roughly 22 calls/second, while transient bus connections hit CreateItem / ReadAlias / Properties.GetAll / StartServiceByName on org.kde.secretservicecompat at the same rate. This also explains why killing ksecretd does not help: clients re-activate it immediately. The item being rewritten is the PSK of the *currently active* wifi connection, with Created == Modified == now - it is continuously deleted and recreated. ksecretd signal serials advanced by >1.17M in ~34 minutes (~570 broadcasts/s), and kdewallet_attributes.json (85 KB) is rewritten constantly, producing an inotify storm. TRIGGER AND USER-VISIBLE SYMPTOM It starts when a *new* wifi network with a password is added. The giveaway is that the password prompt appears twice - first the inline prompt in the panel, then a separate dialog. That is the agent not knowing whether the first write went through. It is intermittent, not every save - I have hit it only a handful of times over a long period, on an ordinary WPA2-PSK network (key-mgmt=wpa-psk, PMF disabled) with nothing to distinguish it from the ~90 other WPA2-PSK networks that saved fine. Open networks never trigger it, since nothing is written. WORKAROUND THAT WORKS systemctl --user restart plasma-kded6.service Because the entry is already in the wallet, the restarted agent finds it, has nothing to write, and the loop cannot re-ignite. Measured immediately after the restart: during the loop after restarting kded6 kwalletd6 RSS 2.7 GB, +600 MB/min 15-20 MB, flat ksecretd CPU ~22 % sustained 0 % MOVED_TO events dozens per second 0 CPU package temp 81 C 49 C The secret stays in the wallet; nothing needs to be moved out of it. TWO NEGATIVE RESULTS THAT MAY SAVE OTHERS TIME - "Close When Idle=true" in kwalletrc does NOT help. The loop itself generates hundreds of accesses per second, so the wallet is never idle and the timer never fires. Tried it: RSS still reached 2.7 GB and the OOM killer stepped in twice. - Killing ksecretd appears to help but only because the wallet locks as a side effect. Once it is unlocked again the loop resumes. It also comes back without --pam-login, which breaks the automatic unlock for the rest of the session. ONE MORE DATA POINT FOR THE ACCUMULATION THEORY While the wallet was locked, kwalletd6 RSS dropped from 1.7 GB to 663 MB on its own, and resumed growing after unlocking. So the memory is reachable and tied to serving requests, which fits accumulating client-side async objects rather than a classic leak. Happy to provide the full D-Bus capture or run further instrumentation if useful.
I am adding this report because my reproduction appears to match the reported kwalletd6 Secret Service memory leak, including recovery after restarting kwalletd6. I believe I am experiencing the same issue described in this report on Fedora 44 KDE Plasma. ## System information * Fedora Linux 44 KDE Plasma * Plasma version: 6.7.3 * KDE Frameworks version: 6.28.0 * Qt version: 6.11.1 * Kernel: 7.1.5-200.fc44.x86_64 * Graphics platform: Wayland Relevant packages: ```text kf6-kwallet-6.28.0-1.fc44.x86_64 kf6-kwallet-libs-6.28.0-1.fc44.x86_64 kf5-kwallet-5.116.0-5.fc44.x86_64 kf5-kwallet-libs-5.116.0-5.fc44.x86_64 kwalletmanager5-26.04.3-1.fc44.x86_64 pam-kwallet-6.7.3-1.fc44.x86_64 signon-kwallet-extension-26.04.3-1.fc44.x86_64 ``` Plasma packages are version: ```text 6.7.3-1.fc44.x86_64 ``` ## Symptoms After a period of normal desktop use, kwalletd6 gradually enters a bad state. Observed symptoms: * Applications using stored secrets begin failing. * NetworkManager fails to retrieve stored Wi-Fi credentials. * D-Bus requests to kwalletd6 eventually time out. * Secret Service-related errors appear continuously in the kwalletd6 journal. * Restarting kwalletd6 temporarily restores normal operation. ## Before restart The affected kwalletd6 process: ```text PID ELAPSED %CPU %MEM RSS 24379 1-14:18:42 25.1 2.9 976924 ``` At this point: * `kwalletd6` still owns the D-Bus name. * `ksecretd` is running and provides `org.freedesktop.secrets`. * The Secret Service interface can enumerate the `kdewallet` collection. * However, `kwalletd6` no longer responds to D-Bus calls. Examples: ```text busctl --user tree org.kde.kwalletd6 Failed to introspect object ...: Connection timed out ``` and: ```text busctl --user call org.kde.kwalletd6 ... Call failed: Connection timed out ``` ## Secret Service state `ksecretd` appears healthy. `busctl --user tree org.freedesktop.secrets` returns: ```text /org/freedesktop/secrets /collection/kdewallet ``` The collection contains items and reports: ```text Label: kdewallet Items: 15 Locked: true ``` This suggests the wallet database exists and the Secret Service layer is active, but kwalletd6 stops servicing requests. ## Journal messages The following messages appear repeatedly: ```text received unexpected result type ao from Completed signal instead of expected o g_task_return_error: assertion 'error != NULL' failed GTask secret_service_real_prompt_async finalized without ever returning ``` In addition, kwalletd6 emits a large number of Qt timer errors: ```text QObject::killTimer(): Error: timer id 721424634 is not valid for object 0x7ffe5c882450 (KWalletD, ), timer has not been killed QObject::killTimer(): Error: timer id 738201851 is not valid for object 0x7ffe5c882450 (KWalletD, ), timer has not been killed QObject::killTimer(): Error: timer id 754979068 is not valid for object 0x7ffe5c882450 (KWalletD, ), timer has not been killed ... ``` These appear in a rapid sequence with increasing invalid timer IDs, all referencing the same `KWalletD` object. ## Recovery Restarting kwalletd6 restores functionality: ```bash systemctl --user restart 'dbus-:1.2-org.kde.kwalletd6@1.service' ``` After restart: ```text PID ELAPSED %CPU %MEM RSS 58780 01:17 22.9 0.3 118784 ``` D-Bus introspection works again: ```text busctl --user tree org.kde.kwalletd6 ``` returns: ```text /MainApplication /modules /modules/kwalletd5 /modules/kwalletd6 /org/kde/kwalletd ``` The KWallet password prompt appears after restart, which is expected because the daemon's unlocked in-memory session is lost. ## Additional observation The issue appears to recur after additional uptime. The restart is a temporary recovery, not a permanent fix. The behavior appears consistent with a Secret Service session/prompt handling problem causing kwalletd6 resource growth and eventual loss of D-Bus responsiveness.
Trigger found: name conflict over org.freedesktop.secrets with gnome-keyring I hit this bug on Arch (Plasma 6.7.4, kwallet 6.28.0, libsecret 0.21.7) with gnome-keyring 1:50.0 installed alongside. The trigger turned out to be gnome-keyring-daemon owning the org.freedesktop.secrets D-Bus name. Once it was out of the picture, the leak stopped and has not returned. THE CORE ISSUE gnome-keyring returns a Prompt object path but never creates the object: Unlock -> object path "/org/freedesktop/secrets/prompt/u1" Prompt.Prompt on that path: Error org.freedesktop.DBus.Error.UnknownMethod: No such object path Introspect /org/freedesktop/secrets/prompt: <node> <- empty The counter increments on each attempt (u1, u2, u3), so every request announces a new prompt without ever registering it on the bus. A spec-compliant client then waits forever for Completed -- which is exactly the GTask secret_service_real_prompt_async (...) finalized without ever returning received unexpected result type ao from Completed signal instead of expected o pair seen on the kwalletd6 side. Starting gcr-prompter by hand makes it register org.gnome.keyring.SystemPrompter and PrivatePrompter correctly and changes nothing, so the fault is in the daemon itself, not in prompter availability. WHY THIS ONLY SURFACED NOW On this system gnome-keyring has been socket-activated since 2024 and caused no trouble for years. Symptoms appeared only after KWallet moved to the kwalletd6 + ksecretd split, where kwalletd6 itself acts as a Secret Service client. That suggests gnome-keyring is not the cause here but merely exposes the new code path -- and that a guard on the kwalletd6 side is the right place to fix it. RESOLUTION Either mask the daemon: systemctl --user mask --now gnome-keyring-daemon.service \ gnome-keyring-daemon.socket or uninstall gnome-keyring entirely, which is what I ended up doing. Removal is straightforward where dependents require the virtual org.freedesktop.secrets provider rather than gnome-keyring by name, since kwallet provides it as well. Note that ~/.local/share/keyrings/ survives removal but nothing is left that can read it, so migrate any secrets you still need first. Either way ksecretd takes over org.freedesktop.secrets. kwalletd6 went from ~900 MB/min growth at 95% CPU to a steady 57 MB at essentially zero CPU, and D-Bus traffic dropped from ~50,000 to ~10 messages per 4 seconds. WHAT DID NOT HELP apiEnabled=false in kwalletrc, and unloading the kded networkmanagement module. The latter came back after a plasma-kded6 restart and the loop still did not reappear with gnome-keyring gone -- to me the strongest indication that the name conflict is the culprit rather than the module. QUICK CHECK FOR OTHERS dbus-send --session --print-reply --dest=org.freedesktop.DBus \ /org/freedesktop/DBus org.freedesktop.DBus.GetConnectionUnixProcessID \ string:org.freedesktop.secrets If the returned PID belongs to gnome-keyring-daemon instead of ksecretd, this is likely the same situation. CAVEAT This is a single environment and it need not explain every occurrence; reporters on openSUSE or Fedora may not have gnome-keyring installed at all. Regardless, a guard on the kwalletd6 side seems worth considering -- a timeout or a retry limit while waiting for Completed -- so that a broken Secret Service implementation on the other end cannot cause unbounded memory growth.
(In reply to Tomasz C. from comment #8) > The trigger turned out to be gnome-keyring-daemon owning the > org.freedesktop.secrets D-Bus name. Once it was > out of the picture, the leak stopped and has not returned. Good find! > gnome-keyring returns a Prompt object path but never creates the object: > Unlock -> object path "/org/freedesktop/secrets/prompt/u1" The spec doesn't explicitly specify prompt paths (another part where it's incomplete), but I suspect it should have been a numeric ID: `.../1`, `.../2`, etc. But `/org/freedesktop/secrets/prompt` being empty is also wrong, I think. https://specifications.freedesktop.org/secret-service/latest/object-paths.html Regardles of KDE's side, this is worth reporting to GNOME Keyring, as this looks like a bug on their end, and possibly a regression. > WHY THIS ONLY SURFACED NOW > Symptoms appeared only after KWallet moved to the kwalletd6 + ksecretd split That split was done over a year ago, in KDE Frameworks 6.14. Yet the memory leak reports only appeared about a month ago. I can think of two possible reasons: 1. A recent regression in GNOME Keyring breaking their prompt creation. 2. A recent regression in kwalletd causing it to use the public org.freedesktop.secrets interface instead of its internal org.kde.secretservicecompat interface. Normally, kwalletd uses the internal interface to talk to ksecrted, unless ksecrted is explicitly disabled in kwalletrc. > WHAT DID NOT HELP > apiEnabled=false in kwalletrc That simply disables the public API in ksecretd (leaving only its internal address). > Regardless, a guard on the kwalletd6 side seems worth considering -- a timeout or > a retry limit while waiting for Completed -- so that a broken Secret Service > implementation on the other end cannot cause unbounded memory growth. I think the key fix on kwalletd side is to make sure it's using its internal address as intended. But I agree that guarding the waits is also desirable.
Since comment #8 explicitly asks whether the gnome-keyring conflict explains every occurrence, here is a data point from the openSUSE side where it does not, and the difference may help narrow down the fix. gnome-keyring is not installed at all on this system. org.freedesktop.secrets is owned by KeePassXC with its FdoSecrets integration enabled, and ksecretd does not compete for that name, because kwalletrc here contains: [org.freedesktop.secrets] apiEnabled=false That is the same setting listed under "what did not help" in comment #8, and as comment #9 explains, it leaves ksecretd with only its internal address. It matters here that it was already in place well before the leak episode I described in comment #6 - I checked that against my own session logs rather than trusting my memory, and that section of the file was not touched during the incident. Its origin is unknown to me: I did not set it, there is no system-wide kwalletrc under /etc/xdg or /usr/share/kf6, and the string appears in the ksecretd binary but not in kwalletd6. The practical consequence is that at the time of my episode nothing was contesting org.freedesktop.secrets - a third-party provider simply held it uncontested - and the loop still happened. To test hypothesis (2) from comment #9 I captured session bus traffic while driving read-only wallet calls, with kwalletd6 as :1.26, ksecretd as :1.15 and KeePassXC as :1.47: mc :1.26 -> org.kde.secretservicecompat /org/freedesktop/secrets Secret.Service.ReadAlias mc :1.26 -> org.kde.secretservicecompat /.../collection/kdewallet DBus.Properties.Get mr :1.15 -> :1.26 (replies) There was not a single message to :1.47, so kwalletd6 talks to ksecretd over the internal name exactly as intended and is not wrongly reaching for the public interface on this machine. My notes from the incident itself say the looping traffic also went to org.kde.secretservicecompat, with CreateItem, ReadAlias, Properties.GetAll and StartServiceByName at the same rate as the kded6 writePassword calls I quantified in comment #6 - the internal path again. I should be honest about how much weight that carries: the raw capture lived in /tmp and is long gone, my journal no longer reaches back that far, and my notes do not state outright that those transient connections belonged to kwalletd6, though it is by far the most plausible candidate. Please treat it as a recollection backed by written notes rather than evidence I can still produce on request. If it does hold, then the broken prompt completion can arise on the internal kwalletd6 to ksecretd path with no foreign Secret Service provider involved at all, which would make removing gnome-keyring a way to remove one trigger rather than the fix. It also argues that the guard proposed at the end of comment #8 and echoed in #9, a timeout or a retry limit while waiting for Completed, is worth having regardless of what sits on the other end. One further observation seems worth recording for other users, since KDE alongside KeePassXC is a common pairing: KeePassXC has the same gap that comment #8 describes for gnome-keyring, only more pronounced. busctl --user introspect org.freedesktop.secrets /org/freedesktop/secrets -> aliases, collection busctl --user introspect org.freedesktop.secrets /org/freedesktop/secrets/prompt -> No such object path '/org/freedesktop/secrets/prompt' There is no prompt node at all, not even the empty one reported for gnome-keyring, and no session node either, while ksecretd exposes aliases, collection and session. Anyone who lets KeePassXC hold org.freedesktop.secrets while kwalletd6 does reach for the public name should therefore expect the same hang. As for the current state here, restarting the plasma-nm secret agent with systemctl --user restart plasma-kded6.service, as described in comment #6, has held for 19 days: kwalletd6 sits at 26 MB and ksecretd at 30 MB, both at 0% CPU, the journal shows no GTask, "finalized without ever returning" or "unexpected result type" lines, and a watchdog checking RSS and the wallet inotify rate every minute has not fired once in over 3000 runs. I can capture the bus traffic properly if the loop comes back, and would welcome direction on what would be most useful to record if it does.
Correcting myself on the last part of my previous comment: the claim about KeePassXC does not hold, and I would rather retract it here than have anyone build on it. I concluded there that KeePassXC never exposes /org/freedesktop/secrets/prompt or a session node, and inferred the same failure mode described for gnome-keyring in comment #8. The introspection output I quoted is real, but my reading of it was wrong, because the measurement was: busctl opens a fresh D-Bus connection per invocation, and a Secret Service session is bound to the client connection, so it was already gone by the time I looked for it. Those nodes are created on demand rather than kept around, so their absence on an idle system means nothing. Repeating the test inside a single connection with dbus-python gives the opposite result: OpenSession returned /org/freedesktop/secrets/session/0b937bc4... /org/freedesktop/secrets/session -> exists the returned session path -> exists, org.freedesktop.Secret.Session Session.Close() -> succeeds So KeePassXC 2.7.12 registers the object properly, and its binary implements the Prompt, Session and Collection interfaces. Please disregard my "same gap as gnome-keyring, only more pronounced" sentence and the prediction that followed it - neither is supported. To be precise about what remains open: I did not test the prompt path itself, which would need the database locked so a client actually receives a prompt object path back, and I have not done that. So this is not evidence that KeePassXC handles prompts correctly either - it simply is not evidence of the opposite, which is what I wrongly suggested. The rest of my previous comment stands: no gnome-keyring on this system, no contest over org.freedesktop.secrets at the time of the episode, and kwalletd6 observed talking to ksecretd over the internal name.
Created attachment 194986 [details] Check whether a Secret Service provider registers the Prompt object it returns Following up on the open point from my correction: I have now checked the prompt path itself, and KeePassXC registers the object it hands back. Lock() on the collection returns /org/freedesktop/secrets/prompt/<id>, and introspecting that path on the same connection finds a real object carrying org.freedesktop.Secret.Prompt. Unlock() returned "/" here because the database was already unlocked, so the path I exercised was the one from Lock(). That is the opposite of what comment #8 reports for gnome-keyring, where the returned path has nothing behind it, and it supports reading that as a bug on their side rather than something inherent to being a non-KDE Secret Service provider. One limitation worth stating: I did not carry the prompt through to completion, so I have not observed the signature of KeePassXC's Completed signal - which is the part that actually misbehaves in this bug. Only the registration of the prompt object was verified. I am attaching the test script in case it is useful to anyone checking their own provider. It has to hold a single D-Bus connection throughout, because busctl and dbus-send open a fresh connection per call while these objects are bound to the client connection - which is exactly what led me to the wrong conclusion I retracted above.
I went through the remaining paths systematically, and the result argues against the objection I raised earlier, so it seems only fair to say so plainly. In libsecret 0.21.7 the prompt is asked for a specific type in three places only: secret-paths.c:1080 wants "ao" for lock and unlock, while :1684 and :1948 want "o" for CreateCollection and CreateItem respectively. The "expected o, received ao" message can therefore only come from the latter two - Unlock is ruled out by construction, and the spec agrees, since Unlock and Lock both take and return arrays of object paths. Measuring each of those against ksecretd over org.kde.secretservicecompat, on kwalletd6 6.28.0: Lock / Unlock prompt completes with "ao" - matches what libsecret asks for CreateItem unlocked collection -> prompt "/", no prompt at all locked collection -> org.freedesktop.Secret.Error.IsLocked CreateCollection prompt /org/freedesktop/secrets/prompt/p2 Completed carries "o" - matches So ksecretd does not produce the mismatch on any path that libsecret types. That undercuts what I wrote in my earlier comment, where I argued the loop on my machine must have arisen on the internal kwalletd6 to ksecretd path with no foreign provider involved. If ksecretd cannot generate that signature at all, then something else did, and the name-conflict finding in comment #8 carries more weight than I gave it. Three caveats, so this is not read as more than it is. I measured 6.28.0-1.2 while the episode I reported happened on 6.28.0-1.1. I only exercised the three operations libsecret types, not every path through the service. And my recollection about the looping traffic going to the internal name cannot be re-checked, since that capture is gone - as I noted when I first mentioned it. Two small things that may be useful anyway. ksecretd numbers its prompts p1, p2 and registers them, so the empty prompt node reported for gnome-keyring in comment #8 does look like the odd one out. And CreateItem against a locked collection failing with IsLocked rather than handing back an unlock prompt means that particular combination cannot be where the mismatch enters, which I had assumed it might be.
Adding a data point from openSUSE Tumbleweed that closely matches the plasma-nm/ kded6 retry loop described here — including the "new WiFi network" trigger — with two details I haven't seen in this report or in bug 522307: the loop occurred WITHOUT gnome-keyring installed, and the retried writePassword calls alternated between TWO different PSK values, which turned out to be my mistyped first attempt and the correct second attempt from the same join flow. It appears every unacknowledged save request retries forever, not just the most recent one. Environment: - openSUSE Tumbleweed, Plasma 6.7.3, kf6-kwallet / kwalletd6 6.28.0, kwalletmanager 26.04.3, pam_kwallet6 6.7.3 - gnome-keyring NOT installed; ksecretd (started via --pam-login) owns org.freedesktop.secrets and org.kde.secretservicecompat - Problem first appeared after upgrading to Plasma 6.7 / 6.7.1 I've had two episodes with different drivers: Episode 1 (2026-07-31) — kwalletd6-driven, same pattern as bug 522307: kwalletd6 called ReadAlias + CreateItem against ksecretd ~40/sec; each colliding CreateItem minted a renamed "__0_" duplicate entry in the wallet; ~175 folderUpdated signals/sec; the kwalletmanager tray applet redrew on every signal (1h28m accumulated CPU). Killing kwalletd6 stopped it; the respawned instance stayed quiet. Episode 2 (2026-08-09) — kded6-driven; killing kwalletd6 did NOT help: Trigger: I connected to a new Wi-Fi network. I mistyped the password at the first prompt, was re-prompted, entered it correctly, and connected successfully. A few minutes later the CPU storm was underway. Observed: - dbus-monitor showed kded6 (plasma-nm secret agent) calling org.kde.KWallet.writePassword ~40-55/sec (277 calls in a 5s window), every call targeting the same entry: folder: "Network Management" key: "{<connection-uuid>};802-11-wireless-security" - Successive payloads ALTERNATED between the mistyped PSK and the correct one — i.e. both save requests from the join flow were being retried indefinitely, interleaved. Each call used a different wallet handle, with `open` / `networkWallet` calls at the same rate (the agent re-opened the wallet per write). - kwalletd6 mirrored each write into ksecretd (SearchItems + CreateItem at the same rate), producing ~120-140 folderUpdated signals/sec sustained. - Resource impact: kwalletd6 RSS grew to 7.7 GB; after I killed it, the fresh instance reached 8.1 GB within ~13 minutes while the loop continued. ksecretd sat at 20-30% CPU, kwalletmanager at 60-67%, CPU package temp 93 C. What did NOT stop episode 2: - Killing kwalletd6 (fresh D-Bus-activated instance immediately re-entered the loop) - Unloading the kded networkmanagement module via org.kde.kded6.unloadModule("networkmanagement") — loadedModules confirmed it gone, but kded6 kept issuing writePassword at the same rate, so the agent object apparently survives module unload. What DID stop it, instantly: systemctl --user restart plasma-kded6.service folderUpdated went from ~1160/10s to 0/10s, and all three processes dropped to 0% CPU. (I then killed the bloated kwalletd6 once more purely to reclaim the leaked RSS; it respawned clean and stayed quiet.) Possibly relevant negative results: during episode 2 the user journal contained NONE of the log messages mentioned in this report — no GTask "finalized without ever returning", no "unexpected result type", no invalid-timer warnings, no QWizard::field messages. Combined with gnome-keyring being absent, this suggests the retry loop does not require the broken-Prompt-provider trigger — consistent with the note that there's no defensive timeout even when the Secret Service provider is functioning. One user-visible consequence others may hit: since the last retry to land wins, the wallet can end up storing the MISTYPED password even though the connection succeeded (NetworkManager still held the correct one in memory), so the next reconnect fails once and re-prompts. Happy to provide exact package versions or re-capture dbus-monitor traces (passwords redacted) if useful.
Confirming comment #14 from the other openSUSE side, and correcting something of my own while I am at it. The negative result Brian reports is the part I can back up. My episode in July was the same shape as his second one - the loop driven by kded6 writePassword against the PSK of the connection I had just joined, killing kwalletd6 not helping, and systemctl --user restart plasma-kded6.service stopping it instantly. Checking my notes from that night, I never recorded a single GTask "finalized without ever returning" or "unexpected result type" line from my own journal either. I should be straightforward about what that means for my earlier comment: when I wrote that my observations matched that backtrace and the ao versus o signature mismatch, I was taking the explanation from this report and applying it to my case, not reporting something I had measured. The journal from that night has since rotated, so I cannot go back and check. Two openSUSE machines showing this loop with none of those messages present seems worth stating plainly. There is one detail from my setup that neither of the other reports has, and it may help separate the two failure modes. On my machine org.freedesktop.secrets is owned by neither ksecretd nor gnome-keyring, but by KeePassXC, because kwalletrc here carries apiEnabled=false under [org.freedesktop.secrets] and ksecretd therefore never claims the public name. Brian has ksecretd owning it; the original reporters had gnome-keyring. All three configurations produce the same kded6 retry loop, which suggests the loop does not care who holds that name at all. I also checked ksecretd against the three operations libsecret types a prompt for, as described in my previous comment, and it answers correctly in every one of them. Taken together with the absent log messages, my reading is that this report may be covering two different problems: the Secret Service prompt leak in the original description, which produces those GTask messages and appears to need a provider that mishandles prompts, and the kded6 writePassword retry loop, which produces no such messages and happens with a perfectly well-behaved provider. If that is right, then my objection in an earlier comment about the loop not requiring a broken provider was closer to the mark than my own follow-up gave it credit for - but it applies to the retry loop, not to the leak this bug was opened about. One small thing to add to Brian's observation about two passwords alternating. In my case the password was asked for twice during the join - an inline prompt in the panel and then a separate dialog - and the connection succeeded. Under his reading that would mean two save requests were in flight from a single join flow, which fits, though I have no capture left to confirm it.
A second episode on the same machine today, this time caught while it was happening, which lets me answer the question about log messages properly rather than from memory. The trigger was the same as in July: joining a new network at a hotel, where the password was requested twice during the join. A few minutes later the loop was running. What it looked like, from the wallet daemon side: 16:01 5714 MOVED_TO events on kdewallet_attributes.json in that single minute 16:01:56 kwalletd6 RSS 553 MB 16:01:57 plasma-kded6 restarted, kwalletd6 killed, ~540 MB freed 16:13 kwalletd6 39 MB and falling, dbus-monitor quiet (4 lines in 5 s) That is roughly 300 MB per minute, which is the same order as the growth reported in comment #14, and on a machine with 8 GB it would have reached the OOM killer within minutes had nothing intervened. The part I could not establish before is what the journal contained. Here is every distinct message ksecretd and kwalletd6 produced in the twenty minutes around the episode, by count: 28572 got event "..." for entry "..." [file] "..." 11428 -->got CREATE signal for "..." sub_entry= 0x0 3 Structure: QMultiHash(...) / Default wallet: "..." 1 Failed to register with host portal QDBusError(...) 0 GTask / finalized without ever returning / unexpected result type Zero across the whole user journal for the surrounding half hour. So this confirms what Brian reported in comment #14, from a third configuration: the kded6 retry loop runs to the point of exhausting memory without emitting any of the prompt or GTask diagnostics this report was opened around. It also settles the caveat I raised in my previous comment - I had said I could not verify my own case because the journal had rotated, and now I can, on a fresh occurrence. One detail consistent with Brian's reading that the agent reopens the wallet on every write: the episode touched several different temporary files in the wallet directory, each accumulating hundreds of MODIFY and ATTRIB events, rather than one file being rewritten. The recovery in this case was automatic. After the July episode I put a small watchdog on a one-minute systemd user timer that restarts plasma-kded6 when kwalletd6 RSS crosses a threshold or the inotify rate on the wallet attribute file goes over 30 per minute. This was its first real trigger in 23 days, and it cut the loop 56 seconds after the threshold was crossed. I mention it because anyone hit by this repeatedly can contain the damage without waiting for a fix, and I am happy to attach the script if that is useful. No lasting damage to the wallet here: no renamed duplicate entries of the kind described in the first episode of comment #14, entry count up by the expected amount for one new network, and the connection works normally.
(In reply to Branislav Klocok from comment #16) > A second episode on the same machine today, this time caught while it was > happening, > which lets me answer the question about log messages properly rather than > from memory. > > The trigger was the same as in July: joining a new network at a hotel, where > the password > was requested twice during the join. A few minutes later the loop was > running. What it > looked like, from the wallet daemon side: > > 16:01 5714 MOVED_TO events on kdewallet_attributes.json in that > single minute > 16:01:56 kwalletd6 RSS 553 MB > 16:01:57 plasma-kded6 restarted, kwalletd6 killed, ~540 MB freed > 16:13 kwalletd6 39 MB and falling, dbus-monitor quiet (4 lines in 5 > s) > > That is roughly 300 MB per minute, which is the same order as the growth > reported in > comment #14, and on a machine with 8 GB it would have reached the OOM killer > within > minutes had nothing intervened. > > The part I could not establish before is what the journal contained. Here is > every > distinct message ksecretd and kwalletd6 produced in the twenty minutes > around the episode, > by count: > > 28572 got event "..." for entry "..." [file] "..." > 11428 -->got CREATE signal for "..." sub_entry= 0x0 > 3 Structure: QMultiHash(...) / Default wallet: "..." > 1 Failed to register with host portal QDBusError(...) > 0 GTask / finalized without ever returning / unexpected result type > > Zero across the whole user journal for the surrounding half hour. So this > confirms what > Brian reported in comment #14, from a third configuration: the kded6 retry > loop runs to > the point of exhausting memory without emitting any of the prompt or GTask > diagnostics > this report was opened around. It also settles the caveat I raised in my > previous comment > - I had said I could not verify my own case because the journal had rotated, > and now I > can, on a fresh occurrence. > > One detail consistent with Brian's reading that the agent reopens the wallet > on every > write: the episode touched several different temporary files in the wallet > directory, each > accumulating hundreds of MODIFY and ATTRIB events, rather than one file > being rewritten. > > The recovery in this case was automatic. After the July episode I put a > small watchdog on > a one-minute systemd user timer that restarts plasma-kded6 when kwalletd6 > RSS crosses a > threshold or the inotify rate on the wallet attribute file goes over 30 per > minute. This > was its first real trigger in 23 days, and it cut the loop 56 seconds after > the threshold > was crossed. I mention it because anyone hit by this repeatedly can contain > the damage > without waiting for a fix, and I am happy to attach the script if that is > useful. > > No lasting damage to the wallet here: no renamed duplicate entries of the > kind described > in the first episode of comment #14, entry count up by the expected amount > for one new > network, and the connection works normally. Confirmed on OpenSUSE Tumbleweed. Happens indeed after joining a new wifi, where I get a second prompt for the password. About 20 to 30 minutes later, kwalletd6 is using 18+GB of RAM and machine crashes.
*** Bug 524500 has been marked as a duplicate of this bug. ***
https://invent.kde.org/frameworks/kwallet/-/commit/068d7d07ad4fa2ce126cc9565c39529926d58c93 fixes some memory leaks in kwalletd6, can you please retest with 6.30 once that is released?
For the time being, while waiting for the upstream fix to reach distribution packages, I set up a systemd user timer as a containment workaround. It checks kwalletd6's anonymous memory once per minute. At 256 MiB it displays a persistent notification with a "Restart KWallet" button, which restarts the daemon to reclaim the leaked memory. The monitor script, systemd service, timer, and installation instructions are here: https://gist.github.com/D3SOX/35cb7d112661b99259496259a4a61c27 The monitor can be removed once the fixed KWallet version is installed.
(In reply to Nico from comment #20) > For the time being, while waiting for the upstream fix to reach distribution > packages, I set up a systemd user timer as a containment workaround. > > It checks kwalletd6's anonymous memory once per minute. At 256 MiB it > displays a persistent notification with a "Restart KWallet" button, which > restarts the daemon to reclaim the leaked memory. > > The monitor script, systemd service, timer, and installation instructions > are here: > > https://gist.github.com/D3SOX/35cb7d112661b99259496259a4a61c27 > > The monitor can be removed once the fixed KWallet version is installed. Lol, I was a bit more drastic and just added a cron entry that kills kwalletd6 every 2 minutes. There is no real consequence, it just restarts itself, which is totally fine.
*** Bug 525331 has been marked as a duplicate of this bug. ***
For those manually or using a timer to kill off kwallet, might I suggest looking at `cgroups`, specifically `MemoryMax=<#>` for systemd units, where the process is killed when that threshold has been reached. It can't be done with a simple "systemctl edit --user" command though. Unit: dbus-:<#>.<#>-org.kde.kwalletd@<#>.service 1) $ systemctl status --user <...> //get the current transient iteration. start with "dbus" and double-tab for bash-completion to list out what exists. 2) $ cat <...> //display contents of the unit file in path from the status output 3) $ systemctl edit --user --full --force <...> //normally nice with regular unit files, but not transients. ***Need to strip out ":<#>.<#>" and "@<#>" (but keep the "@" itself) 4) copy/paste contents from "cat" 5) add "MemoryMax=<#>" under the "[Service]" section. <#>="1G" for example if you want to be generous. 6) systemctl stop --user <unit> //just to kill existing transient so override can take effect with the next iterative run. This is partly pseudo. I haven't tried it for this service, but have used cgroups in general successfully.
Some observations from local debugging: I've been tracking this memory growth locally and wanted to share a few observations regarding how these components interact during this state: 1: kwalletd6 behavior: It acts as a passive, event-driven daemon handling incoming D-Bus requests. The rapid memory growth (~14 MB/s RSS in my environment) appears to be a downstream effect driven by an unusually high volume of incoming traffic—specifically continuous CreateItem and GetProperties requests for org.freedesktop.Secret.Item.Attributes. 2: Client-side request frequency: Monitoring D-Bus traffic indicates that plasma-nm (inside kded6) enters a high-frequency retry/polling loop under specific conditions (such as syncing a specific Wi-Fi credential UUID like {...};802-11-wireless-security). 3: Cascade effect: When this loop triggers at ~10ms intervals, session and proxy objects are instantiated faster than the standard lifecycle cleanup can process them, leading to high CPU load in kded6 and steady RSS growth in kwalletd6.
Retested on 6.30.0 as asked in comment #19. Three runs today, all clean, but I want to be upfront about what that does and does not show. Setup: openSUSE Tumbleweed, kwalletd6 and kf6-kwallet 6.30.0 installed on 13 September, Plasma on Wayland. Rather than waiting for this to happen on its own I triggered it deliberately with a phone hotspot, since joining a new password-protected network is what started it for me in July and again in August. I sampled kwalletd6 and ksecretd RSS, kded6 CPU and the rate of org.kde.KWallet.writePassword calls every two seconds throughout. The first run was a plain join with the correct password on the first try. Fifteen minutes, 395 samples: kwalletd6 went up by 1.4 MB once as the secret was written and then stayed flat, with no writePassword traffic at all afterwards. The third run is the interesting one, because it reproduces the sequence from comment #14 exactly. I deliberately mistyped the password, got a second prompt, entered the correct one and connected. NetworkManager logged both secret requests from that single join: secrets required first prompt, wrong password secrets exist second prompt, correct password Activation: successful, device activated Eleven minutes after that connection: kwalletd6 grew by 20 kB in total, writePassword stayed at 0/s across 77 separate measurements, kded6 sat at 0.0% CPU, and no GTask or "unexpected result type" lines appeared. For comparison, in July this machine was losing roughly 600 MB per minute at this point, and in August I measured 553 MB in under two minutes with 5714 inotify events on the wallet attribute file in a single minute. Now the caveat, which matters more than the numbers. This bug has always been intermittent for me. Over the years I hit it a handful of times, not on every network I joined, so the overwhelming majority of joins were always quiet even before your fix. Three clean runs are therefore a good sign and nothing more. I cannot tell you the leak is gone, only that I could not provoke it today along the path that provoked it twice before. I will keep the RSS watchdog running and will report back if it ever fires again, which is probably the more useful signal over the next few weeks of travelling. One unrelated thing I ran into while setting this up, in case it is useful to someone. On a WPA3/SAE network a wrong password leaves the profile permanently stuck: NetworkManager reports that secrets exist, retries the stored one, fails, and never asks the agent for a new one, so there is no way to correct it from the applet. On WPA2-PSK the second prompt appears normally. The wrong password also gets written to the wallet even when the connection fails, which lines up with what was reported in comment #14 about the mistyped password winning.