From 2a796ba8d8ea873a94d58c4a270687e36ce682f0 Mon Sep 17 00:00:00 2001 From: Tudor Voicu Date: Tue, 19 Oct 2021 14:32:59 +0200 Subject: [PATCH] ErrorFactories.invalidArgumentWasNotFound for handling invalid event ids --- .../api/validation/ErrorFactories.scala | 20 +++++++++++++++++++ .../api/validation/ErrorFactoriesSpec.scala | 19 ++++++++++++++++++ .../transaction/ApiTransactionService.scala | 4 ++-- 3 files changed, 41 insertions(+), 2 deletions(-) diff --git a/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/ErrorFactories.scala b/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/ErrorFactories.scala index 6cf8e2a7fa02..a3c3524bedf2 100644 --- a/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/ErrorFactories.scala +++ b/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/ErrorFactories.scala @@ -160,6 +160,26 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch .asGrpcError, ) + // This error builder covers cases where existing logic handling invalid arguments returned NOT_FOUND. + def invalidArgumentWasNotFound(definiteAnswer: Option[Boolean])(message: String)(implicit + contextualizedErrorLogger: ContextualizedErrorLogger + ): StatusRuntimeException = + errorCodesVersionSwitcher.choose( + v1 = { + val statusBuilder = Status + .newBuilder() + .setCode(Code.NOT_FOUND.value()) + .setMessage(message) + addDefiniteAnswerDetails(definiteAnswer, statusBuilder) + grpcError(statusBuilder.build()) + }, + // TODO error codes: This error group is confusing for this generic error as it can be dispatched + // from call-sites that do not involve command validation (e.g. ApiTransactionService). + v2 = LedgerApiErrors.CommandValidation.InvalidArgument + .Reject(message) + .asGrpcError, + ) + /** @param fieldName An invalid field's name. * @param message A status' message. * @param definiteAnswer A flag that says whether it is a definite answer. Provided only in the context of command deduplication. diff --git a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/platform/server/api/validation/ErrorFactoriesSpec.scala b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/platform/server/api/validation/ErrorFactoriesSpec.scala index 228f43fa3a8e..aa1671564bb7 100644 --- a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/platform/server/api/validation/ErrorFactoriesSpec.scala +++ b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/platform/server/api/validation/ErrorFactoriesSpec.scala @@ -338,6 +338,25 @@ class ErrorFactoriesSpec extends AnyWordSpec with Matchers with TableDrivenPrope } } + "return an invalidArgument (with legacy error code as NOT_FOUND) error" in { + val testCases = Table( + ("definite answer", "expected details"), + (None, Seq.empty), + (Some(false), Seq(definiteAnswers(false))), + ) + + forEvery(testCases) { (definiteAnswer, expectedDetails) => + assertVersionedError(_.invalidArgumentWasNotFound(definiteAnswer)("my message"))( + v1_code = Code.NOT_FOUND, + v1_message = "my message", + v1_details = expectedDetails, + v2_code = Code.INVALID_ARGUMENT, + v2_message = + s"INVALID_ARGUMENT(8,$correlationId): The submitted command has invalid arguments: my message", + ) + } + } + "should create an ApiException without the stack trace" in { val status = Status.newBuilder().setCode(Code.INTERNAL.value()).build() val exception = grpcError(status) diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/transaction/ApiTransactionService.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/transaction/ApiTransactionService.scala index 1f07d5091e10..8807eca27a55 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/transaction/ApiTransactionService.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/transaction/ApiTransactionService.scala @@ -142,7 +142,7 @@ private[apiserver] final class ApiTransactionService private ( } .getOrElse { Future.failed { - errorFactories.invalidArgument(None)(s"invalid eventId: ${request.eventId}") + errorFactories.invalidArgumentWasNotFound(None)(s"invalid eventId: ${request.eventId}") } } .andThen(logger.logErrorsOnCall[GetTransactionResponse]) @@ -185,7 +185,7 @@ private[apiserver] final class ApiTransactionService private ( } .getOrElse { val msg = s"eventId: ${request.eventId}" - Future.failed(errorFactories.invalidArgument(None)(msg)) + Future.failed(errorFactories.invalidArgumentWasNotFound(None)(msg)) } .andThen(logger.logErrorsOnCall[GetFlatTransactionResponse]) }