Skip to main content

Session Outcome

Statuses, result fields and failure codes of EUDIPLO sessions, as returned by GET /api/session/{id}, sent in SSE events and in webhooks. How to receive them is described in Receive Results.

Statusesโ€‹

StatusPresentation sessionIssuance session
activeRequest created; the wallet has not fetched it yet.Offer created.
fetchedThe wallet fetched the request object. ISO 18013-7 sessions skip this status.The first credential of the session was issued.
completedThe presentation was verified.The wallet reported credential_accepted (Notifications).
failedVerification failed, or the wallet sent an error response (for example the user declined).The wallet reported credential_failure or credential_deleted.
expiredexpiresAt passed before the session finished.The offer expired before it was redeemed (Credential Offers).

Sessions only move forward: active โ†’ fetched โ†’ completed, failed or expired. The last three are terminal; a later wallet request is rejected with 400, and a late response never overwrites the final status.

Expiry is enforced when a wallet uses the session: a presentation request or response after expiresAt gets 400 ("The session has expired"). The status itself changes to expired when the session maintenance job runs, every SESSION_TIDY_UP_INTERVAL seconds (default 3600). Until then an overdue session still shows active or fetched.

Result fieldsโ€‹

FieldContent
statusSee above.
credentialsOnly when completed. OpenID4VP: [{ "id": "<query id>", "values": [ { <claims> } ] }], one values entry per presented credential. ISO 18013-7: [{ "id", "format": "mso_mdoc", "docType", "claims" }].
outcomeStructured result, see below. Set on completed and failed.
failureCodeStable code of a classified failure, see failure codes. Absent for other failures.
errorReasonShort, display-safe description of the failure.
responseCodeOne-time code of a completed OpenID4VP or ISO 18013-7 presentation; compare it with the response_code of a same-device redirect.
consumedAtWhen the presentation completed.
expiresAtWhen the request expires (presentation configuration lifeTime, default 300 seconds).
transaction_dataThe transaction data sent with the request.

Outcomeโ€‹

{
"result": "failed",
"error": "trust_chain_not_trusted",
"message": "The credential issuer is not in the trusted list.",
"credentials": [
{
"id": "pid",
"format": "mso_mdoc",
"docType": "eu.europa.ec.eudi.pid.1",
"verified": false,
"error": "trust_chain_not_trusted",
"message": "The credential issuer is not in the trusted list."
}
]
}
FieldContent
resultsuccess or failed.
errorFailure code; same value as failureCode. Only for classified failures.
messageShort, display-safe message; same value as errorReason.
credentials[]Per credential query. On success every presented query with "verified": true; on a classified verification failure the credential that failed, with its error and message.
credentials[].format, docTypeCredential format and, for mDOC, the docType, when known.
credentials[].trustISO 18013-7 success only: the matched trust list entry (matchedIssuer, issuanceThumbprint, matchMode, revocationThumbprint).

Branch on error; treat message as display text. Detailed diagnostics, such as certificate subjects or trust list URLs, are never part of the outcome; they go to the server log and the session log.

Failure codesโ€‹

Credential verificationโ€‹

The same codes are used for SD-JWT VC and mDOC, in OpenID4VP and ISO 18013-7 flows.

CodeMessageCause
signature_invalidThe credential signature is invalid.Issuer or device signature does not verify: tampered credential, wrong session transcript or key mismatch.
no_trust_chain_to_rootThe credential issuer does not chain to a trusted root.No certificate path from the credential's certificate to a certificate in the trust list.
trust_chain_not_trustedThe credential issuer is not in the trusted list.A path exists, but it matches no PID or EAA issuance entry of the trust list.
trust_list_unavailableThe trusted list could not be loaded, so the credential could not be validated.A configured trust list could not be fetched, parsed or signature-checked, or its NextUpdate has passed. EUDIPLO fails closed. This is a verifier-side problem.
certificate_expiredThe credential issuer certificate is expired or not yet valid.A certificate in the path is outside its validity period.
x5c_missingThe credential is missing its issuer certificate chain.The credential carries no x5c certificate chain.
verification_errorThe credential could not be verified.Any other verification error, including a malformed x5c and federation trust failures.

DCQL claim valuesโ€‹

CodeMessageCause
claim_value_mismatchDisclosed claim values do not match the requested values for credential '<id>': <paths>A disclosed claim is not one of the values of its claim query. With claim_sets, no set matched and at least one disclosed claim had another value.

The message names the credential query and the claim paths, never the disclosed values. The outcome has no credentials entry for this code. A mismatch is reported before missing claims of the same credential.

Wallet error responsesโ€‹

When the wallet answers with an OAuth error instead of a presentation, for example because the user declined, EUDIPLO records the wallet's code as failureCode (access_denied, invalid_request, vp_formats_not_supported, wallet_unavailable, ...). errorReason and outcome.message read Wallet error: <error>: <error_description>. The wallet gets HTTP 200, as OpenID4VP 1.0 ยง8.2 requires, with a redirect_uri carrying error and error_description if a redirect is configured. EUDIPLO accepts the error both as form parameters and inside an encrypted direct_post.jwt response.

Other failuresโ€‹

Some failures have no code; failureCode and outcome.error are absent and errorReason describes the problem. Examples:

  • Missing required credentials: ... or Missing required claims for credential '...': ...: the response does not satisfy the DCQL query.
  • Presentation validation failed: ...: for example a transaction data hash mismatch, an invalid key binding, or several presentations for a query without multiple.
  • HPKE decryption failed: an ISO 18013-7 response that cannot be decrypted.

What the wallet or browser receivesโ€‹

An OpenID4VP response that fails verification is answered with 400; with a configured redirect the body contains redirect_uri with error=invalid_request and the message as error_description. An ISO 18013-7 response that fails verification is answered with 400 and the code:

{
"statusCode": 400,
"timestamp": "2026-10-03T10:01:12.000Z",
"path": "/presentations/3f0c1d9e-4c1b-4f63-9a59-2f4f0b6a2c11/iso-18013-7",
"error": "trust_chain_not_trusted",
"message": "The credential issuer is not in the trusted list."
}

Session logsโ€‹

GET /api/session/{id}/logs returns the log entries stored for a session (timestamp, level (info, warn or error), stage, message, detail). Entries are only stored when LOG_SESSION_STORE is errors (warnings and errors), all or verbose (also request and response bodies); the default off stores nothing. See Environment Variables.