Skip to content

Handle empty presentation matches without crashing#438

Open
nodh wants to merge 3 commits intodevelopmentfrom
fix/436-exception-handler
Open

Handle empty presentation matches without crashing#438
nodh wants to merge 3 commits intodevelopmentfrom
fix/436-exception-handler

Conversation

@nodh
Copy link
Copy Markdown
Member

@nodh nodh commented Mar 20, 2026

Summary

  • reject Presentation Exchange descriptors that have no matching stored credential before the selection UI is built
  • guard related selection and presentation-result code paths that assumed non-empty collections
  • add a regression test for the empty-match Presentation Exchange case

Verification

  • ./gradlew :shared:testAndroidHostTest --tests ui.presentation.CredentialSelectionProviderTest

Fixes #436

iOS Build is fixed in #434

@nodh nodh requested a review from gp-iaik March 20, 2026 11:20
@nodh nodh self-assigned this Mar 20, 2026
@nodh nodh changed the base branch from main to development March 20, 2026 11:21
@chatgpt-codex-connector
Copy link
Copy Markdown

💡 Codex Review

check(missingDescriptorIds.isEmpty()) {
"Presentation definition input descriptor(s) ${
missingDescriptorIds.joinToString(", ")
} did not match any stored credential"

P1 Badge Route empty presentation matches to the no-credential UI

When a presentation-exchange request has any input descriptor with zero matches, this check now throws while building selectionProvider. DefaultPresentationGraphViewModel catches that as UiStateError, and PresentationGraphView immediately forwards UiStateError to the global error handler, so users get kicked out of the consent flow instead of seeing the existing “no matching credential” screen. This regression is easy to hit with unsupported credential types or over-constrained descriptors.


authenticationResult.authenticationResponseResult.params.let {
val serializedResponse = vckJsonSerializer.encodeToString(it)
walletMain.presentationService.finalizeOid4vpDCAPIPresentation(serializedResponse)

P1 Badge Preserve response_mode-specific DC API payload formatting

When an OpenID4VP DC API request finishes with AuthenticationForward, this now serializes the whole authenticationResponseResult.params object and hands it to prepareDCAPIOid4vpCredentialResponse. On Android that string is forwarded verbatim to CredMan (shared/src/androidMain/kotlin/main.android.kt:352-355), but the removed implementation only sent params.response for plain dc_api and wrapped it differently for dc_api.jwt. As a result, relying parties using the unsigned DC API response mode will now receive the wrong wire format and reject the callback.


if (!processedItemIds.contains(item.storeEntryId)) {
RefreshConfirmationDialog(
entry = item.entry,
onConfirm = {
processedItemIds = processedItemIds + item.storeEntryId
walletMain.credentialValidityService.refreshSingleWithStatus(item)

P2 Badge Keep confirmed single-item refresh requests reachable

After the user confirms the one-item refresh dialog, this stores the storeEntryId in processedItemIds, which permanently suppresses that dialog for the same item. Because the only navigation path to RefreshCenterRoute is the separate items.size > 1 branch below, a single refresh request that later ends in Failed or Succeeded but remains in refreshItems can no longer be retried or dismissed anywhere in the UI. That leaves one refresh item stuck until another item appears or the list is cleared externally.

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@nodh nodh requested a review from gp-iaik March 25, 2026 08:04
@nodh nodh force-pushed the fix/436-exception-handler branch from 2111956 to 45ae9b1 Compare March 25, 2026 08:05
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.

Requesting non-existant document type during presentation exchange crashes app

2 participants