Skip to content

fix(desktop): make sidebar endpoint resilient to unmatched profile scopes (#67600) - #67617

Open
webtecnica wants to merge 1 commit into
NousResearch:mainfrom
webtecnica:fix/67600-default-sidebar
Open

fix(desktop): make sidebar endpoint resilient to unmatched profile scopes (#67600)#67617
webtecnica wants to merge 1 commit into
NousResearch:mainfrom
webtecnica:fix/67600-default-sidebar

Conversation

@webtecnica

@webtecnica webtecnica commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Refs #67600 — the default profile sidebar renders empty when the Desktop client sends a recents_profile that doesn't exactly match "default" case-sensitively.

Root Cause

get_profiles_sessions_sidebar at line 4511 uses an exact case-sensitive comparison (name == recents_scope). If the Desktop client sends "Default", "", or any other non-exact identifier, the default profile never matches and the recents slice silently returns zero rows with no error.

Fix

After computing recents_scope and before entering the per-profile loop, validate it against known profile names from list_profiles():

  1. Case-insensitive match first — if recents_scope differs only in case from a known profile name, use the canonical casing.
  2. Fall back to "default" — if the scope doesn't match any profile name at all (empty, wrong case with no match, bare path, etc.), use "default" as the scopee.
  3. Surface a warning — push a diagnostic entry into the errors list so the client can see that a fallback occurred. This makes the bug class visible instead of silently returning an empty list.

The errors list was moved up from line 4474 to before the validation block so warnings can be appended before the per-profile loop runs.

Behavior Matrix

recents_profile sent Before After
"default" ✅ 20 rows ✅ 20 rows
"Default" ❌ 0 rows, silent ✅ 20 rows (case-match), no warning
"" ❌ 0 rows, silent ✅ 20 rows, warning in errors
"/Users/…/.hermes" ❌ 0 rows, silent ✅ 20 rows, warning in errors
"all" ✅ all profiles ✅ all profiles (unchanged)

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard comp/desktop Electron desktop app (apps/desktop/*) area/profiles Multi-profile isolation, HERMES_HOME scoping needs-decision Awaiting maintainer decision before any implementation labels Jul 19, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

This was generated by AI during triage.

Related to #67600. The fallback handles invalid profile scopes, while current-main tracing of that report sends default; a maintainer should confirm this is the intended residual path.

@teknium1 teknium1 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Thanks for adding diagnostics around an otherwise silent sidebar result.

Problems

  • The later reproduction evidence on #67600 shows the affected packaged Desktop build calls /api/profiles/sessions?profile=default, not /api/profiles/sessions/sidebar. That legacy route is handled by hermes_cli/web_server.py:4294-4329, while this PR only changes the batched route at hermes_cli/web_server.py:4421. The captured request already carries the canonical default scope, so this change cannot affect the reported production path.
  • The new fallback at hermes_cli/web_server.py:4484 substitutes default-profile recents for any unmatched scope. That can hide the caller defect and show a different profile's sessions instead of retaining the requested-profile semantics.
  • Current coverage exercises only recents_profile=all in tests/hermes_cli/test_web_server.py:1845-1871; it does not cover either new normalization branch.

Suggested changes

  • Re-scope from the captured released-client request/renderer path in #67600, after validating its response body and consumption path.
  • Avoid default-profile substitution for arbitrary invalid scopes unless that behavior is explicitly intended, and add regression coverage for the selected contract.

Automated hermes-sweeper review.

Comment thread hermes_cli/web_server.py
f'falling back to "default"'
),
})
recents_scope = "default"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

An unmatched scope now displays the default profile's recents rather than preserving the requested profile or reporting a distinguishable validation failure. #67600's captured release request already sends profile=default to the separate /api/profiles/sessions route, so this substitution cannot address that repro and can mask a wrong caller scope.

@teknium1 teknium1 added sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform labels Jul 19, 2026
@zakhounet

Copy link
Copy Markdown
Contributor

Thanks for picking this up so quickly. The hardening here is worth having on its own — the silent zero-row return was the second problem I raised in #67600, and surfacing a warning in errors fixes exactly that class of invisible failure.

One thing I wanted to flag before merge, in case it's useful: I'm not sure this will change the symptom on my setup, and if so it might be worth keeping #67600 open.

Timing-wise this PR landed at 17:49, shortly after the scope-divergence hypothesis and a little before I posted a packet capture testing it — so the data below simply wasn't available yet when you wrote the fix. It came out the other way:

1. The affected client never calls /api/profiles/sessions/sidebar.

Two captures on the backend host — one against the published release, one against a build I compiled from 299e409f1 — show only the three per-slice calls:

GET /api/profiles/sessions?…&profile=default&exclude_sources=cron,subagent,tool,telegram,…,webhook,api_server,…
GET /api/profiles/sessions?…&profile=all&source=cron
GET /api/profiles/sessions?…&profile=all&exclude_sources=cron,cli,codex,desktop,gateway,local,tui

No request to get_profiles_sessions_sidebar is ever emitted, on either build. So a change confined to that handler cannot alter the behaviour I'm seeing.

2. On this setup there doesn't seem to be a scope mismatch to repair.

The value sent for the root profile is profile=default — verbatim, correctly cased, not empty, not a path. As far as I can tell each row of your behaviour matrix corresponds to an input my client doesn't produce. Replaying that exact recents query server-side against the profile DB returns a full page of 50 rows, so the data is there and the server would serve it.

3. It reproduces on a source build of main.

I packed the Desktop from 299e409f1 on the affected machine; it connects (established sessions to the backend) and the default list is still empty. So this is not a stale-release problem that HEAD already fixes.

Small suggestion

The resilience change is worth landing regardless. Would you consider switching Fixes #67600 to Refs #67600, so the report stays open until the symptom is confirmed gone? Otherwise merging would close it while the empty list is presumably still there, and whoever hits it next starts from scratch.

One loose end from my last comment that may be the more promising thread: listSidebarSessions is reached at use-session-list-actions.ts:168 with no guard ahead of it, and the string is present in the built renderer bundle — yet no such request is ever emitted at runtime. I couldn't work out why. If something is bypassing that call site, the batched endpoint wouldn't be in the failing path at all, which would also explain why my captures never show it.

Happy to run any capture or instrumented build you'd like on the affected machine.

@zakhounet

Copy link
Copy Markdown
Contributor

@webtecnica following up on the one small thing from my earlier comment: would you consider changing Fixes #67600 to Refs #67600 in the description? As it stands, merging this closes that report automatically, and the symptom there is untouched by this change.

Since I wrote that comment I've pinned a bisection window on #67600, which I think settles it:

commit date result
Good 614dc194e 2026-07-18 19:21 root profile lists normally
Bad 299e409f1 2026-07-19 17:29 root profile empty
Still bad aa274364b 2026-07-20 16:46 root profile empty

Both boundaries are local builds from a checkout, on two machines against one backend. Within that window, exactly one commit touches apps/desktop/src/app/session/hooks/use-session-list-actions.ts: 40160e2a0 (#67245). So the defect looks client-side, in how the session store is populated — not in the endpoint this PR hardens.

None of that argues against landing your change. The silent zero-row return was a real problem and surfacing it in errors is worth having on its own. It just isn't the fix for #67600, and I'd rather the report stayed open until the empty sidebar is confirmed gone — if you don't mind.

@GottZ

GottZ commented Aug 3, 2026

Copy link
Copy Markdown

This was generated by AI during triage.

Summary

Three PRs address or reference #67600: merged #67245 introduced the batched sidebar fan-out whose primary-profile requests bypassed OAuth-aware authentication; open #67617 hardens unmatched server-side profile scopes but does not touch that authenticated client path; closed #71503 routes those requests through the OAuth-aware helper and matches the reported cause.

Related pull requests

Duplicates

#71503 and merged #72835 implement essentially the same OAuth-aware authentication fix for the primary sidebar session slices; #71503 is superseded by #72835. #67617 is not a duplicate because it changes server-side scope normalization instead.

Suggested consolidation

Treat #67600 as implemented on main by merged #72835 at commit 704a32187, as documented and independently reproduced in the issue discussion; retain #67245 as the regression-source reference and #71503 as the closed, superseded best-fix reference. For #67617, author action: rebase onto main and split out the independently useful diagnostics or safe scope-normalization hardening with targeted tests and without claiming to fix #67600; this follows the contributor's keep_open review rather than recommending closure or integration over its stated semantic and coverage concerns.

Cross-PR triage: Reviewed 3 pull requests and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 41 kB of PR diffs, 15 kB of issue/PR text, 23 kB of discussion (17 comments), 2 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area/profiles Multi-profile isolation, HERMES_HOME scoping comp/cli CLI entry point, hermes_cli/, setup wizard comp/desktop Electron desktop app (apps/desktop/*) needs-decision Awaiting maintainer decision before any implementation P3 Low — cosmetic, nice to have sweeper:blast-moderate Sweeper blast radius: moderate — a subsystem or single platform sweeper:risk-compatibility Sweeper risk: may break existing users, config, migrations, defaults, or upgrades type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants