diff --git a/ledger/error/src/main/scala/com/daml/error/utils/ErrorDetails.scala b/ledger/error/src/main/scala/com/daml/error/utils/ErrorDetails.scala index 67385cf08d..d773154d63 100644 --- a/ledger/error/src/main/scala/com/daml/error/utils/ErrorDetails.scala +++ b/ledger/error/src/main/scala/com/daml/error/utils/ErrorDetails.scala @@ -68,7 +68,7 @@ object ErrorDetails { case ErrorInfoDetail(errorCodeId, _) => errorCodeId == errorCode.id case _ => false } - val matchesMessagePrefix = e.getStatus.getDescription.startsWith(errorCode.id) + val matchesMessagePrefix = Option(e.getStatus.getDescription).exists(_.startsWith(errorCode.id)) val matchesStatusCode = errorCode.category.grpcCode.contains(e.getStatus.getCode) matchesErrorCodeId && matchesMessagePrefix && matchesStatusCode } diff --git a/ledger/error/src/test/suite/scala/com/daml/error/utils/ErrorDetailsSpec.scala b/ledger/error/src/test/suite/scala/com/daml/error/utils/ErrorDetailsSpec.scala new file mode 100644 index 0000000000..532738eb1f --- /dev/null +++ b/ledger/error/src/test/suite/scala/com/daml/error/utils/ErrorDetailsSpec.scala @@ -0,0 +1,51 @@ +// Copyright (c) 2022 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. +// SPDX-License-Identifier: Apache-2.0 + +package com.daml.error.utils + +import com.daml.error.ErrorCategory.BackgroundProcessDegradationWarning +import com.daml.error.definitions.LedgerApiErrors +import com.daml.error.{DamlContextualizedErrorLogger, ErrorClass, ErrorCode} +import io.grpc.{Status, StatusRuntimeException} +import org.scalatest.flatspec.AnyFlatSpec +import org.scalatest.matchers.should.Matchers + +class ErrorDetailsSpec extends AnyFlatSpec with Matchers { + + private val errorLogger = DamlContextualizedErrorLogger.forTesting(getClass) + + behavior of classOf[ErrorDetails.type].getName + + it should "correctly match exception to error codes " in { + val securitySensitive = + LedgerApiErrors.AuthorizationChecks.Unauthenticated.MissingJwtToken()(errorLogger).asGrpcError + val notSecuritySensitive = LedgerApiErrors.AdminServices.UserNotFound + .Reject(_operation = "operation123", userId = "userId123")(errorLogger) + .asGrpcError + + ErrorDetails.matches( + securitySensitive, + LedgerApiErrors.AuthorizationChecks.Unauthenticated, + ) shouldBe false + ErrorDetails.matches( + notSecuritySensitive, + LedgerApiErrors.AdminServices.UserNotFound, + ) shouldBe true + ErrorDetails.matches( + new StatusRuntimeException(Status.ABORTED), + LedgerApiErrors.AdminServices.UserNotFound, + ) shouldBe false + ErrorDetails.matches(new Exception, LedgerApiErrors.AdminServices.UserNotFound) shouldBe false + + object NonGrpcErrorCode + extends ErrorCode( + id = "NON_GRPC_ERROR_CODE_123", + BackgroundProcessDegradationWarning, + )(ErrorClass.root()) + NonGrpcErrorCode.category.grpcCode shouldBe empty + ErrorDetails.matches( + new StatusRuntimeException(Status.ABORTED), + NonGrpcErrorCode, + ) shouldBe false + } +} diff --git a/ledger/ledger-api-bench-tool/src/main/scala/com/daml/ledger/api/benchtool/services/UserManagementService.scala b/ledger/ledger-api-bench-tool/src/main/scala/com/daml/ledger/api/benchtool/services/UserManagementService.scala index 08ad7c103e..d288cb0b03 100644 --- a/ledger/ledger-api-bench-tool/src/main/scala/com/daml/ledger/api/benchtool/services/UserManagementService.scala +++ b/ledger/ledger-api-bench-tool/src/main/scala/com/daml/ledger/api/benchtool/services/UserManagementService.scala @@ -4,6 +4,7 @@ package com.daml.ledger.api.benchtool.services import com.daml.error.definitions.LedgerApiErrors +import com.daml.error.utils.ErrorDetails import com.daml.ledger.api.benchtool.AuthorizationHelper import com.daml.ledger.api.v1.admin.user_management_service.{ CreateUserRequest, @@ -32,9 +33,7 @@ class UserManagementService(channel: Channel, authorizationToken: Option[String] val rights = userRights(observerPartyNames, signatoryPartyName) createUser(userId, rights).recoverWith { case e: StatusRuntimeException - if e.getStatus.getDescription.startsWith( - LedgerApiErrors.AdminServices.UserAlreadyExists.id - ) => + if ErrorDetails.matches(e, LedgerApiErrors.AdminServices.UserAlreadyExists) => logger.info( s"Benchmark user already exists (received error: ${e.getStatus.getDescription}) so granting rights the existing user." ) diff --git a/ledger/ledger-api-tests/infrastructure/src/main/scala/com/daml/ledger/api/testtool/infrastructure/participant/UserManagementTestContext.scala b/ledger/ledger-api-tests/infrastructure/src/main/scala/com/daml/ledger/api/testtool/infrastructure/participant/UserManagementTestContext.scala index d24ce3041f..d42f53f549 100644 --- a/ledger/ledger-api-tests/infrastructure/src/main/scala/com/daml/ledger/api/testtool/infrastructure/participant/UserManagementTestContext.scala +++ b/ledger/ledger-api-tests/infrastructure/src/main/scala/com/daml/ledger/api/testtool/infrastructure/participant/UserManagementTestContext.scala @@ -6,6 +6,7 @@ package com.daml.ledger.api.testtool.infrastructure.participant import java.util.concurrent.ConcurrentHashMap import com.daml.error.definitions.LedgerApiErrors +import com.daml.error.utils.ErrorDetails import com.daml.ledger.api.testtool.infrastructure.LedgerServices import com.daml.ledger.api.v1.admin.user_management_service.UserManagementServiceGrpc.UserManagementService import com.daml.ledger.api.v1.admin.user_management_service.{ @@ -15,7 +16,6 @@ import com.daml.ledger.api.v1.admin.user_management_service.{ DeleteUserResponse, User, } -import io.grpc.StatusRuntimeException import scala.concurrent.{ExecutionContext, Future} @@ -70,10 +70,7 @@ trait UserManagementTestContext { ) .map(_ => ()) .recover { - case e: StatusRuntimeException - if e.getStatus.getDescription.startsWith( - LedgerApiErrors.AdminServices.UserNotFound.id - ) => + case e if ErrorDetails.matches(e, LedgerApiErrors.AdminServices.UserNotFound) => () } )