Apps portlet list shows 0 configurations when the secrets store is unreadable, instead of reporting the error
Nobody has claimed this yet.
- Dominant language
- Java
- Stars
- 970
- Forks
- 486
- Avg merge
- 3d 33m
- Merged PRs (30d)
- 170
Description
Description
The Apps portlet list reports every app as 0 configurations when the secrets store cannot be read, while opening an app's detail raises an error. An administrator sees "nothing is configured", clicks in, and gets a failure — two surfaces telling them different things about the same store.
This is a layering problem, not a missing throw. The portlet is answering an administrative question with a runtime API:
| Caller | Question being asked | Right answer when the store is unreadable |
|---|---|---|
EMAWebInterceptor, SAML, Velocity $secrets, analytics, telemetry |
"Is this app configured for this site?" | Degrade. Treat as not configured and keep serving the request. |
| Apps portlet list | "What is the state of App configuration?" | Say so. "I cannot read the store" is the single most important thing to report. |
Both go through AppsAPIImpl.filterSitesForAppKey, which AppsHelper:124 calls to compute configurationsCount. That method deliberately catches Exception and returns "no secrets for this site", because it runs on every /api/* request via EMAWebInterceptor — making it raise returns a 500 for the entire API, which is a regression that was already found and fixed once in PR #37053 (94ea3579e6).
So the fix is not to make filterSitesForAppKey throw. It is to give the admin surface an explicit store-health signal instead of inferring state from a count that is designed to degrade.
Current behaviour
With a store this node cannot decrypt (cluster-salt rotation, or a per-node SECRETS_KEYSTORE_PASSWORD_KEY):
GET /api/v1/apps -> 200, every app "configurationsCount": 0
GET /api/v1/apps/{key}/{siteId} -> 500
Observed on a container built from PR #37053.
Impact
Misinformation, not data loss. The admin cannot destroy anything from this state — saving also goes through getSecretsStore(), which raises, so a "re-enter the credentials" reaction fails loudly rather than overwriting an intact store (verified: the store's checksum was unchanged after a save attempt). The cost is that the list actively points away from the real problem, which is a mis-set salt or password, at exactly the moment someone is trying to diagnose it.
Not a regression: before #37053 the store was silently wiped and recreated empty, so the list also showed 0 — having just destroyed the credentials.
Acceptance Criteria
- The Apps portlet list surfaces "the App secrets store cannot be read" as an explicit condition, rather than rendering it as
0 configurations. - The signal is carried on its own channel —
getAvailableDescriptorViewsWithErrorsalready returns aList<AppDescriptorLoadError>alongside the views, which is the natural place, or an equivalent field. -
AppsAPIImpl.filterSitesForAppKeystill does not raise. Its runtime callers (EMAWebInterceptoron every/api/*request,InitRunner.isUveEnabled(), SAML, telemetry) must keep degrading. A regression here returns a 500 for the whole API. - The UI distinguishes "0 configurations" from "state unknown" — an administrator must not read an unreadable store as an empty one.
- The message points at the actual cause: the store could not be decrypted, usually a changed cluster salt or a per-node
SECRETS_KEYSTORE_PASSWORD_KEY. The wording inSecretsKeyStoreHelper.handleUnrecoverableLoadis a good starting point. - The detail view's existing hard error is preserved.
- Test coverage for the list against an unreadable store.
Additional Context
Raised in review of PR #37053 (issue #36724), which stopped an unreadable secrets store from being silently wiped. That PR documents the split at the decision point in AppsAPIImpl.filterSitesForAppKey and deliberately left closing it to a follow-up, because surfacing the condition in the list is a UI-facing change with its own signal path.
Frontend work is likely required alongside the backend signal.
Severity
Low - Cosmetic or minor issue
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with AppsAPIImpl.filterSitesForAppKey and AppsHelper:124, then trace getAvailableDescriptorViewsWithErrors and the Apps portlet list UI. Compare the existing error wording in SecretsKeyStoreHelper.handleUnrecoverableLoad. Done means the list carries and displays an unreadable-store condition separately from 0 configurations, while runtime callers still degrade and the detail error remains.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- java
- Domain
- backend, frontend
- Issue type
- Bug
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 54/100