From ec6d7cc3dbf1bf9bdd3f7289a1d63231e4815424 Mon Sep 17 00:00:00 2001 From: tudor-da Date: Mon, 15 Nov 2021 22:28:13 +0100 Subject: [PATCH] [Self-service error codes] Error code definitions revisiting [DPP-675] (#11686) * Error definitions revisiting and hierarchical grouping refactoring CHANGELOG_BEGIN CHANGELOG_END * Full hierarchical path for error grouping * Addressed Pawel's review comments * Apply suggestions from code review Co-authored-by: mziolekda Co-authored-by: pbatko-da * Do not strip margin in error code explanations * Revert changing LEDGER_ID_MISMATCH from NOT_FOUND to FAILED_PRECONDITION Co-authored-by: mziolekda Co-authored-by: pbatko-da --- .../self_service_error_codes_extension.py | 14 +- .../daml/error/definitions/ErrorGroups.scala | 15 +- .../error/definitions/LedgerApiErrors.scala | 1013 ++++++++--------- .../definitions/PackageServiceError.scala | 21 +- .../definitions/PruningServiceError.scala | 25 - .../definitions/RejectionGenerators.scala | 127 +-- .../error/definitions/SubmissionErrors.scala | 58 - .../validation/LedgerOffsetValidator.scala | 8 +- .../api/validation/ErrorFactories.scala | 158 +-- .../api/validation/FieldValidations.scala | 5 +- ...ompletionServiceRequestValidatorTest.scala | 4 +- .../SubmitRequestValidatorTest.scala | 2 +- ...ansactionServiceRequestValidatorTest.scala | 16 +- .../api/validation/ErrorFactoriesSpec.scala | 119 +- .../CommandDeduplicationBase.scala | 8 +- .../suites/ActiveContractsServiceIT.scala | 2 +- .../api/testtool/suites/ClosedWorldIT.scala | 2 +- .../testtool/suites/CommandServiceIT.scala | 30 +- .../CommandSubmissionCompletionIT.scala | 8 +- .../suites/ConfigManagementServiceIT.scala | 8 +- .../api/testtool/suites/ContractIdIT.scala | 5 +- .../api/testtool/suites/ContractKeysIT.scala | 30 +- .../testtool/suites/DeeplyNestedValueIT.scala | 100 +- .../api/testtool/suites/ExceptionsIT.scala | 22 +- .../suites/LedgerConfigurationServiceIT.scala | 6 +- .../suites/MultiPartySubmissionIT.scala | 16 +- .../testtool/suites/PackageServiceIT.scala | 2 +- .../suites/ParticipantPruningIT.scala | 20 +- .../suites/PartyManagementServiceIT.scala | 4 +- .../api/testtool/suites/SemanticTests.scala | 20 +- .../TransactionServiceAuthorizationIT.scala | 4 +- .../suites/TransactionServiceExerciseIT.scala | 2 +- .../suites/TransactionServiceQueryIT.scala | 16 +- .../suites/TransactionServiceStreamsIT.scala | 4 +- .../TransactionServiceValidationIT.scala | 30 +- .../suites/WronglyTypedContractIdIT.scala | 6 +- .../services/ApiCommandService.scala | 2 +- .../services/ApiLedgerIdentityService.scala | 2 +- .../services/ApiPackageService.scala | 7 +- .../services/ApiSubmissionService.scala | 8 +- .../admin/ApiConfigManagementService.scala | 7 +- .../admin/ApiParticipantPruningService.scala | 4 +- .../services/admin/SynchronousResponse.scala | 2 +- .../index/LedgerBackedIndexService.scala | 2 +- .../store/appendonlydao/JdbcLedgerDao.scala | 2 +- .../platform/store/ConversionsSpec.scala | 2 +- .../state/kvutils/errors/KVErrors.scala | 5 +- .../updates/TransactionRejections.scala | 22 +- 48 files changed, 900 insertions(+), 1095 deletions(-) delete mode 100644 ledger/error/src/main/scala/com/daml/error/definitions/PruningServiceError.scala delete mode 100644 ledger/error/src/main/scala/com/daml/error/definitions/SubmissionErrors.scala diff --git a/docs/sphinx_ext/self_service_error_codes_extension.py b/docs/sphinx_ext/self_service_error_codes_extension.py index 8585822b4aed..259fc2f95768 100644 --- a/docs/sphinx_ext/self_service_error_codes_extension.py +++ b/docs/sphinx_ext/self_service_error_codes_extension.py @@ -128,7 +128,7 @@ def build_hierarchical_tree_of_error_data(data) -> defaultdict: # DFS to traverse the error code data tree from `build_hierarchical_tree_of_error_data` # While traversing the tree, the presentation of the error codes on the documentation is built - def dfs(tree, node, prefix: str) -> None: + def dfs(tree, node, numeric_prefix: str, topic_prefix: str) -> None: if 'explanation' in tree and tree['explanation']: node += group_explanation_to_node(tree['explanation']) if 'error-codes' in tree: @@ -140,10 +140,14 @@ def dfs(tree, node, prefix: str) -> None: for subtopic, subtree in tree.items(): if subtopic in ['error-codes', 'explanation']: continue - subprefix = f"{prefix}{i}." + subtree_node_numeric_prefix = f"{numeric_prefix}{i}." i += 1 - subtree_node = text_node(n=nodes.rubric, txt = subprefix + " " + subtopic) - dfs(tree=subtree, node=subtree_node, prefix=subprefix) + topic = subtopic + if topic_prefix != "": + topic = topic_prefix + " / " + subtopic + subtree_node_header = subtree_node_numeric_prefix + " " + topic + subtree_node = text_node(n=nodes.rubric, txt = subtree_node_header) + dfs(tree=subtree, node=subtree_node, numeric_prefix=subtree_node_numeric_prefix, topic_prefix=topic) node += subtree_node for node in doctree.traverse(error_code_node): @@ -155,7 +159,7 @@ def dfs(tree, node, prefix: str) -> None: root = nodes.rubric(rawsource = "", text = "") section += root tree = build_hierarchical_tree_of_error_data(data=error_codes_data.values()) - dfs(tree=tree, node=root, prefix="") + dfs(tree=tree, node=root, numeric_prefix="", topic_prefix="") node.replace_self(new=[section]) diff --git a/ledger/error/src/main/scala/com/daml/error/definitions/ErrorGroups.scala b/ledger/error/src/main/scala/com/daml/error/definitions/ErrorGroups.scala index c883d53959b3..c2fea7edc60f 100644 --- a/ledger/error/src/main/scala/com/daml/error/definitions/ErrorGroups.scala +++ b/ledger/error/src/main/scala/com/daml/error/definitions/ErrorGroups.scala @@ -6,20 +6,15 @@ package com.daml.error.definitions import com.daml.error.{ErrorClass, ErrorGroup} object ErrorGroups { + val rootErrorClass: ErrorClass = ErrorClass.root() - private implicit val errorClass: ErrorClass = ErrorClass.root() - - object ParticipantErrorGroup extends ErrorGroup() { + object ParticipantErrorGroup extends ErrorGroup()(rootErrorClass) { abstract class IndexErrorGroup extends ErrorGroup() { abstract class DatabaseErrorGroup extends ErrorGroup() } - abstract class PackageServiceErrorGroup extends ErrorGroup() - abstract class PruningServiceErrorGroup extends ErrorGroup() - object TransactionErrorGroup extends ErrorGroup() { - // Errors emitted by Ledger Api server - abstract class LedgerApiErrorGroup extends ErrorGroup() - // TransactionSubmissionErrors are routing errors resulting from the transaction processor - abstract class SubmissionErrorGroup extends ErrorGroup() + abstract class LedgerApiErrorGroup extends ErrorGroup() { + abstract class CommandExecutionErrorGroup extends ErrorGroup() + abstract class PackageServiceErrorGroup extends ErrorGroup() } } } diff --git a/ledger/error/src/main/scala/com/daml/error/definitions/LedgerApiErrors.scala b/ledger/error/src/main/scala/com/daml/error/definitions/LedgerApiErrors.scala index 9617133884e2..8a827558d9ab 100644 --- a/ledger/error/src/main/scala/com/daml/error/definitions/LedgerApiErrors.scala +++ b/ledger/error/src/main/scala/com/daml/error/definitions/LedgerApiErrors.scala @@ -3,9 +3,8 @@ package com.daml.error.definitions -import java.time.Duration import com.daml.error._ -import com.daml.error.definitions.ErrorGroups.ParticipantErrorGroup.TransactionErrorGroup.LedgerApiErrorGroup +import com.daml.error.definitions.ErrorGroups.ParticipantErrorGroup.LedgerApiErrorGroup import com.daml.lf.data.Ref import com.daml.lf.data.Ref.PackageId import com.daml.lf.engine.Error.Validation.ReplayMismatch @@ -16,174 +15,226 @@ import com.daml.lf.transaction.GlobalKey import com.daml.lf.value.Value import com.daml.lf.{VersionRange, language} -import java.time.Instant +import java.time.{Duration, Instant} object LedgerApiErrors extends LedgerApiErrorGroup { - - @Explanation("This rejection is given when the requested service has already been closed.") - @Resolution("Contact the participant operator.") - object ServiceNotRunning - extends ErrorCode( - id = "SERVICE_NOT_RUNNING", - // TODO error codes: Re-check this error category - ErrorCategory.TransientServerFailure, - ) { - case class Reject()(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = "Service has been shut down." - ) - } - - object WriteErrors extends ErrorGroup() { - @Explanation("This rejection is given when a configuration entry write was rejected.") - @Resolution("Fetch newest configuration and/or retry.") - object ConfigurationEntryRejected + object CommandExecution extends ErrorGroup { + @Explanation( + """This error occurs if the participant fails to determine the max ledger time of the used + |contracts. Most likely, this means that one of the contracts is not active anymore which can + |happen under contention. It can also happen with contract keys. + |""" + ) + @Resolution("Retry the transaction submission.") + object FailedToDetermineLedgerTime extends ErrorCode( - id = "CONFIGURATION_ENTRY_REJECTED", - ErrorCategory.InvalidGivenCurrentSystemStateOther, + id = "FAILED_TO_DETERMINE_LEDGER_TIME", + ErrorCategory.ContentionOnSharedResources, ) { - case class Reject(message: String)(implicit + + case class Reject(_reason: String)(implicit loggingContext: ContextualizedErrorLogger ) extends LoggingTransactionErrorImpl( - cause = message + cause = + s"The participant failed to determine the max ledger time for this command: ${_reason}" ) } - @Explanation("This rejection is given when a package upload was rejected.") - @Resolution("Refer to the detailed message of the received error.") - object PackageUploadRejected - extends ErrorCode( - id = "PACKAGE_UPLOAD_REJECTED", - ErrorCategory.InvalidGivenCurrentSystemStateOther, - ) { - case class Reject(message: String)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = message - ) + object Package extends ErrorGroup() { + @Explanation( + """This error indicates that the uploaded DAR is based on an unsupported language version.""" + ) + @Resolution("Use a DAR compiled with a language version that this participant supports.") + object AllowedLanguageVersions + extends ErrorCode( + id = "ALLOWED_LANGUAGE_VERSIONS", + ErrorCategory.InvalidIndependentOfSystemState, + ) { + + def buildCause( + packageId: PackageId, + languageVersion: LanguageVersion, + allowedLanguageVersions: VersionRange[LanguageVersion], + ): String = + LfError.Package + .AllowedLanguageVersion(packageId, languageVersion, allowedLanguageVersions) + .message + + case class Error( + packageId: Ref.PackageId, + languageVersion: language.LanguageVersion, + allowedLanguageVersions: VersionRange[language.LanguageVersion], + )(implicit + val loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = buildCause(packageId, languageVersion, allowedLanguageVersions) + ) + } + + @Explanation( + """This error occurs if a package referred to by a command fails validation. This should not happen as packages are validated when being uploaded.""" + ) + @Resolution("Contact support.") + object PackageValidationFailed + extends ErrorCode( + id = "PACKAGE_VALIDATION_FAILED", + ErrorCategory.MaliciousOrFaultyBehaviour, + ) { + case class Reject(validationErrorCause: String)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = validationErrorCause + ) + } } - @Explanation( - "This rejection is given when a request might not been processed and a time-out was reached." - ) - @Resolution( - "Retry for transient problems. If non-transient contact the operator as the time-out limit might be to short." - ) - object RequestTimeOut - extends ErrorCode( - id = "REQUEST_TIME_OUT", - ErrorCategory.DeadlineExceededRequestStateUnknown, - ) { - case class Reject(message: String, override val definiteAnswer: Boolean)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = message - ) + object Preprocessing extends ErrorGroup { + @Explanation("""This error occurs if a command fails during interpreter pre-processing.""") + @Resolution("Inspect error details and correct your application.") + object PreprocessingFailed + extends ErrorCode( + id = "COMMAND_PREPROCESSING_FAILED", + ErrorCategory.InvalidIndependentOfSystemState, + ) { + case class Reject( + err: LfError.Preprocessing.Error + )(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = err.message + ) + } } - } - object ReadErrors extends ErrorGroup() { + object Interpreter extends ErrorGroup { + @Explanation("""This error occurs if a Daml transaction fails during interpretation.""") + @Resolution("This error type occurs if there is an application error.") + object GenericInterpretationError + extends ErrorCode( + id = "DAML_INTERPRETATION_ERROR", + ErrorCategory.InvalidGivenCurrentSystemStateOther, + ) { - @Explanation("This rejection is given when a package id is malformed.") - @Resolution("Make sure the package id provided in the request has correct form.") - // TODO error codes: Consider using `LedgerApiErrors.CommandValidation.InvalidArgument` - object MalformedPackageId - extends ErrorCode( - id = "MALFORMED_PACKAGE_ID", - ErrorCategory.InvalidIndependentOfSystemState, - ) { - case class Reject(message: String)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = message - ) - } + case class Error(override val cause: String)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = cause + ) + } - @Explanation( - "This rejection is given when a read request tries to access a package which does not exist on the ledger." - ) - @Resolution("Use a package id pertaining to a package existing on the ledger.") - // TODO error codes: Possible duplicate of `LedgerApiErrors.Package.MissingPackage` - object PackageNotFound - extends ErrorCode( - id = "PACKAGE_NOT_FOUND", - ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, - ) { - case class Reject(packageId: String)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = "Could not find package." + @Explanation( + """This error occurs if a Daml transaction fails during interpretation due to an invalid argument.""" + ) + @Resolution("This error type occurs if there is an application error.") + object InvalidArgumentInterpretationError + extends ErrorCode( + id = "DAML_INTERPRETER_INVALID_ARGUMENT", + ErrorCategory.InvalidIndependentOfSystemState, ) { - override def resources: Seq[(ErrorResource, String)] = { - super.resources :+ ((ErrorResource.DalfPackage, packageId)) - } + case class Error(override val cause: String)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = cause + ) + } - } - @Explanation("This rejection is given when a read request tries to access pruned data.") - @Resolution("Use an offset that is after the pruning offset.") - object ParticipantPrunedDataAccessed - extends ErrorCode( - id = "PARTICIPANT_PRUNED_DATA_ACCESSED", - // TODO error codes: Rename error category to cover this scenario - // where the data accessed is before the allowed pruning begin - ErrorCategory.InvalidGivenCurrentSystemStateSeekAfterEnd, - ) { - case class Reject(message: String)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = message - ) - } + @Explanation( + """This error occurs if an exercise or fetch happens on a transaction-locally consumed contract.""" + ) + @Resolution("This error indicates an application error.") + object ContractNotActive + extends ErrorCode( + id = "CONTRACT_NOT_ACTIVE", + ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, + ) { - @Explanation( - "This rejection is given when a read request uses an offset beyond the current ledger end." - ) - @Resolution("Use an offset that is before the ledger end.") - object RequestedOffsetOutOfRange - extends ErrorCode( - id = "REQUESTED_OFFSET_OUT_OF_RANGE", - ErrorCategory.InvalidGivenCurrentSystemStateSeekAfterEnd, - ) { - case class Reject(message: String)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = message + case class Reject( + override val cause: String, + _err: LfInterpretationError.ContractNotActive, + )(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = cause + ) { + override def resources: Seq[(ErrorResource, String)] = Seq( + (ErrorResource.ContractId, _err.coid.coid) ) - } + } - @Explanation( - "The transaction does not exist or the requesting set of parties are not authorized to fetch it." - ) - @Resolution( - "Check the transaction id and verify that the requested transaction is visible to the requesting parties." - ) - object TransactionNotFound - extends ErrorCode( - id = "TRANSACTION_NOT_FOUND", - ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, - ) { + } - case class Reject(transactionId: String)(implicit loggingContext: ContextualizedErrorLogger) - extends LoggingTransactionErrorImpl(cause = "Transaction not found, or not visible.") { - override def resources: Seq[(ErrorResource, String)] = Seq( - (ErrorResource.TransactionId, transactionId) + object LookupErrors extends ErrorGroup { + @Explanation( + """This error occurs if the Daml engine interpreter cannot resolve a contract key to an active contract. This + |can be caused by either the contract key not being known to the participant, or not being known to + |the submitting parties or the contract representing an already archived key.""" ) + @Resolution("This error type occurs if there is contention on a contract.") + object ContractKeyNotFound + extends ErrorCode( + id = "CONTRACT_KEY_NOT_FOUND", + ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, + ) { + + case class Reject( + override val cause: String, + _key: GlobalKey, + )(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = cause + ) { + override def resources: Seq[(ErrorResource, String)] = Seq( + (ErrorResource.ContractKey, _key.toString()) + ) + } + } + } + + @Explanation("""This error occurs if a Daml transaction fails due to an authorization error. + |An authorization means that the Daml transaction computed a different set of required submitters than + |you have provided during the submission as `actAs` parties.""") + @Resolution("This error type occurs if there is an application error.") + object AuthorizationError + extends ErrorCode( + id = "DAML_AUTHORIZATION_ERROR", + ErrorCategory.InvalidIndependentOfSystemState, + ) { + + case class Reject(override val cause: String)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = cause + ) } } } - // the authorization checks are here only for documentation purpose. - // TODO error codes: Extract these errors in ledger-api-auth and use them in [[com.daml.ledger.api.auth.Authorizer]] - // (i.e. in lieu of ErrorFactories.permissionDenied() and ErrorFactories.unauthenticated()) - object AuthorizationChecks extends ErrorGroup() { + @Explanation("This rejection is given when the requested service has already been closed.") + @Resolution( + "Retry re-submitting the request. If the error persists, contact the participant operator." + ) + object ServiceNotRunning + extends ErrorCode( + id = "SERVICE_NOT_RUNNING", + ErrorCategory.TransientServerFailure, + ) { + case class Reject(serviceName: String)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = s"$serviceName has been shut down." + ) + } + object AuthorizationChecks extends ErrorGroup() { @Explanation( """This rejection is given if the submitted command does not contain a JWT token on a participant enforcing JWT authentication.""" ) - @Resolution("Ask your participant operator to provide you with an appropriate JWT token.") + @Resolution( + "Ask your participant operator to provide you with an appropriate JWT token." + ) object Unauthenticated extends ErrorCode( id = "UNAUTHENTICATED", @@ -212,11 +263,11 @@ object LedgerApiErrors extends LedgerApiErrorGroup { } @Explanation( - """This rejection is given if the supplied JWT token is not sufficient for the intended command. + """This rejection is given if the supplied authorization token is not sufficient for the intended command. |The exact reason is logged on the participant, but not given to the user for security reasons.""" ) @Resolution( - "Inspect your command and your token, or ask your participant operator for an explanation why this command failed." + "Inspect your command and your token or ask your participant operator for an explanation why this command failed." ) object PermissionDenied extends ErrorCode(id = "PERMISSION_DENIED", ErrorCategory.InsufficientPermission) { @@ -224,355 +275,224 @@ object LedgerApiErrors extends LedgerApiErrorGroup { loggingContext: ContextualizedErrorLogger ) extends LoggingTransactionErrorImpl( cause = - s"The provided JWT token is not sufficient to authorize the intended command: $cause" + s"The provided authorization token is not sufficient to authorize the intended command: $cause" ) } } - object CommandValidation extends ErrorGroup { - @Explanation( - """Every ledger Api command contains a ledger-id which is verifying against the running ledger. - This error indicates that the provided ledger-id does not match the expected one.""" - ) - @Resolution("Ensure that your application is correctly configured to use the correct ledger.") - object LedgerIdMismatch - extends ErrorCode( - id = "LEDGER_ID_MISMATCH", - ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, - ) { - case class Reject(override val cause: String)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = cause, - definiteAnswer = true, - ) - } + object RequestValidation extends ErrorGroup { + object NotFound extends ErrorGroup() { + @Explanation( + "This rejection is given when a read request tries to access a package which does not exist on the ledger." + ) + @Resolution("Use a package id pertaining to a package existing on the ledger.") + object Package + extends ErrorCode( + id = "PACKAGE_NOT_FOUND", + ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, + ) { + case class Reject(packageId: String)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = "Could not find package." + ) { - @Explanation( - """This error is emitted, when a submitted ledger Api command could not be successfully deserialized due to mandatory fields not being set.""" - ) - @Resolution("Inspect the reason given and correct your application.") - object MissingField - extends ErrorCode(id = "MISSING_FIELD", ErrorCategory.InvalidIndependentOfSystemState) { - case class Reject(missingField: String)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = s"The submitted command is missing a mandatory field: $missingField" - ) - } + override def resources: Seq[(ErrorResource, String)] = { + super.resources :+ ((ErrorResource.DalfPackage, packageId)) + } + } - @Explanation( - """This error is emitted, when a submitted ledger Api command contained an invalid argument.""" - ) - @Resolution("Inspect the reason given and correct your application.") - object InvalidArgument - extends ErrorCode(id = "INVALID_ARGUMENT", ErrorCategory.InvalidIndependentOfSystemState) { - case class Reject(_reason: String)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = s"The submitted command has invalid arguments: ${_reason}" - ) - } + case class InterpretationReject( + packageId: PackageId, + reference: Reference, + )(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = LookupError.MissingPackage.pretty(packageId, reference) + ) + } - @Explanation( - """This error is emitted, when a submitted ledger Api command contained a field value that could not be properly understood""" - ) - @Resolution("Inspect the reason given and correct your application.") - object InvalidField - extends ErrorCode(id = "INVALID_FIELD", ErrorCategory.InvalidIndependentOfSystemState) { - case class Reject(_reason: String)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = s"The submitted command has a field with invalid value: ${_reason}" + @Explanation( + "The transaction does not exist or the requesting set of parties are not authorized to fetch it." + ) + @Resolution( + "Check the transaction id and verify that the requested transaction is visible to the requesting parties." + ) + object Transaction + extends ErrorCode( + id = "TRANSACTION_NOT_FOUND", + ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, + ) { + + case class Reject(transactionId: String)(implicit loggingContext: ContextualizedErrorLogger) + extends LoggingTransactionErrorImpl(cause = "Transaction not found, or not visible.") { + override def resources: Seq[(ErrorResource, String)] = Seq( + (ErrorResource.TransactionId, transactionId) ) - } + } + } - @Explanation( - "This error is emitted when a submitted ledger API command specifies an invalid deduplication period." - ) - @Resolution( - "Inspect the error message, adjust the value of the deduplication period or ask the participant operator to increase the maximum." - ) - object InvalidDeduplicationPeriodField - extends ErrorCode( - id = "INVALID_DEDUPLICATION_PERIOD", - ErrorCategory.InvalidGivenCurrentSystemStateOther, - ) { - case class Reject(_reason: String, _maxDeduplicationDuration: Duration)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = s"The submitted command had an invalid deduplication period: ${_reason}" + @Explanation( + "The ledger configuration could not be retrieved. This could happen due to incomplete initialization of the participant or due to an internal system error." + ) + @Resolution("Contact the participant operator.") + object LedgerConfiguration + extends ErrorCode( + id = "LEDGER_CONFIGURATION_NOT_FOUND", + ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, ) { - override def context: Map[String, String] = - super.context + ("max_deduplication_duration" -> _maxDeduplicationDuration.toString) + + case class Reject()(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = "The ledger configuration could not be retrieved." + ) } } - } - - object CommandPreparation extends ErrorGroup { - @Explanation( - """This error occurs if the participant fails to determine the max ledger time of the used - |contracts. Most likely, this means that one of the contracts is not active anymore which can - |happen under contention. However, it can also happen with contract keys. - |""" - ) - @Resolution("Retry the transaction") - object FailedToDetermineLedgerTime + @Explanation("This rejection is given when a read request tries to access pruned data.") + @Resolution("Use an offset that is after the pruning offset.") + object ParticipantPrunedDataAccessed extends ErrorCode( - id = "FAILED_TO_DETERMINE_LEDGER_TIME", - ErrorCategory.ContentionOnSharedResources, + id = "PARTICIPANT_PRUNED_DATA_ACCESSED", + ErrorCategory.InvalidGivenCurrentSystemStateOther, ) { - - case class Reject(_reason: String)(implicit + case class Reject(message: String)(implicit loggingContext: ContextualizedErrorLogger ) extends LoggingTransactionErrorImpl( - cause = - s"The participant failed to determine the max ledger time for this command: ${_reason}" + cause = message ) - } - } - - object Package extends ErrorGroup() { @Explanation( - """This error indicates that the uploaded dar is based on an unsupported language version.""" + "This rejection is given when a read request uses an offset beyond the current ledger end." ) - @Resolution("Use a Dar compiled with a language version that this participant supports.") - object AllowedLanguageVersions + @Resolution("Use an offset that is before the ledger end.") + object OffsetAfterLedgerEnd extends ErrorCode( - id = "ALLOWED_LANGUAGE_VERSIONS", - ErrorCategory.InvalidIndependentOfSystemState, + id = "OFFSET_AFTER_LEDGER_END", + ErrorCategory.InvalidGivenCurrentSystemStateSeekAfterEnd, ) { - - def buildCause( - packageId: PackageId, - languageVersion: LanguageVersion, - allowedLanguageVersions: VersionRange[LanguageVersion], - ): String = - LfError.Package - .AllowedLanguageVersion(packageId, languageVersion, allowedLanguageVersions) - .message - - case class Error( - packageId: Ref.PackageId, - languageVersion: language.LanguageVersion, - allowedLanguageVersions: VersionRange[language.LanguageVersion], - )(implicit - val loggingContext: ContextualizedErrorLogger + case class Reject(offsetType: String, requestedOffset: String, ledgerEnd: String)(implicit + loggingContext: ContextualizedErrorLogger ) extends LoggingTransactionErrorImpl( - cause = buildCause(packageId, languageVersion, allowedLanguageVersions) + cause = s"$offsetType offset ($requestedOffset) is after ledger end ($ledgerEnd)" ) } @Explanation( - """This error occurs if the Daml transaction is referring to a package which is not known to the participant.""" + "This rejection is given when a read request uses an offset invalid in the requests' context." ) - @Resolution("Upload the necessary Dars to the participant node.") - object MissingPackage + @Resolution("Inspect the error message and use a valid offset.") + object OffsetOutOfRange extends ErrorCode( - id = "MISSING_PACKAGE", - ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, + id = "OFFSET_OUT_OF_RANGE", + ErrorCategory.InvalidGivenCurrentSystemStateOther, ) { - case class Reject( - packageId: PackageId, - reference: Reference, - )(implicit + case class Reject(message: String)(implicit loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = LookupError.MissingPackage.pretty(packageId, reference) - ) - + ) extends LoggingTransactionErrorImpl(cause = message) } @Explanation( - """This error occurs if a package referred to by a Command fails validation. This should not happen as packages are validated when being uploaded.""" + """Every ledger API command contains a ledger-id which is verified against the running ledger. + This error indicates that the provided ledger-id does not match the expected one.""" ) - @Resolution("Contact support.") - object PackageValidationFailed - extends ErrorCode( - id = "PACKAGE_VALIDATION_FAILED", - ErrorCategory.MaliciousOrFaultyBehaviour, - ) { - case class Reject(validationErrorCause: String)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = validationErrorCause - ) - } - } - - object PreprocessingErrors extends ErrorGroup { - @Explanation("""This error occurs if a command fails during interpreter pre-processing.""") - @Resolution("Inspect error details and correct your application.") - object PreprocessingFailed + @Resolution("Ensure that your application is correctly configured to use the correct ledger.") + object LedgerIdMismatch extends ErrorCode( - id = "COMMAND_PREPROCESSING_FAILED", - ErrorCategory.InvalidIndependentOfSystemState, + id = "LEDGER_ID_MISMATCH", + ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, ) { - case class Reject( - err: LfError.Preprocessing.Error - )(implicit + case class Reject(override val cause: String)(implicit loggingContext: ContextualizedErrorLogger ) extends LoggingTransactionErrorImpl( - cause = err.message + cause = cause, + definiteAnswer = true, ) } - } - object InterpreterErrors extends ErrorGroup { - - @Explanation("""This error occurs if the Daml transaction failed during interpretation.""") - @Resolution("This error type occurs if there is an application error.") - object GenericInterpretationError - extends ErrorCode( - id = "DAML_INTERPRETATION_ERROR", - ErrorCategory.InvalidGivenCurrentSystemStateOther, - ) { - - case class Error(override val cause: String)(implicit + @Explanation( + """This error is emitted when a mandatory field is not set in a submitted ledger API command.""" + ) + @Resolution("Inspect the reason given and correct your application.") + object MissingField + extends ErrorCode(id = "MISSING_FIELD", ErrorCategory.InvalidIndependentOfSystemState) { + case class Reject(missingField: String)(implicit loggingContext: ContextualizedErrorLogger ) extends LoggingTransactionErrorImpl( - cause = cause + cause = s"The submitted command is missing a mandatory field: $missingField" ) - } @Explanation( - """This error occurs if the Daml transaction failed during interpretation due to an invalid argument.""" + """This error is emitted when a submitted ledger API command contains an invalid argument.""" ) - @Resolution("This error type occurs if there is an application error.") - object InvalidArgumentInterpretationError - extends ErrorCode( - id = "DAML_INTERPRETER_INVALID_ARGUMENT", - ErrorCategory.InvalidIndependentOfSystemState, - ) { - - case class Error(override val cause: String)(implicit + @Resolution("Inspect the reason given and correct your application.") + object InvalidArgument + extends ErrorCode(id = "INVALID_ARGUMENT", ErrorCategory.InvalidIndependentOfSystemState) { + case class Reject(_reason: String)(implicit loggingContext: ContextualizedErrorLogger ) extends LoggingTransactionErrorImpl( - cause = cause + cause = s"The submitted command has invalid arguments: ${_reason}" ) - } @Explanation( - """This error occurs if an exercise or fetch happens on a transaction-locally consumed contract.""" + """This error is emitted when a submitted ledger API command contains a field value that cannot be understood.""" ) - @Resolution("This error indicates an application error.") - object ContractNotActive - extends ErrorCode( - id = "CONTRACT_NOT_ACTIVE", - ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, - ) { - - case class Reject( - override val cause: String, - _err: LfInterpretationError.ContractNotActive, - )(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = cause - ) { - override def resources: Seq[(ErrorResource, String)] = Seq( - (ErrorResource.ContractId, _err.coid.coid) - ) - } - - } - - object LookupErrors extends ErrorGroup { - - @Explanation("""This error occurs if the Damle interpreter can not find a referenced contract. This - |can be caused by either the contract not being known to the participant, or not being known to - |the submitting parties or already being archived.""") - @Resolution("This error type occurs if there is contention on a contract.") - object ContractNotFound - extends ErrorCode( - id = "CONTRACT_NOT_FOUND", - ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, - ) { - - case class Reject( - override val cause: String, - _cid: Value.ContractId, - )(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = cause - ) { - override def resources: Seq[(ErrorResource, String)] = Seq( - (ErrorResource.ContractId, _cid.coid) - ) - } - - } - - @Explanation( - """This error occurs if the Damle interpreter can not resolve a contract key to an active contract. This - |can be caused by either the contract key not being known to the participant, or not being known to - |the submitting parties or the contract representing the key has already being archived.""" - ) - @Resolution("This error type occurs if there is contention on a contract.") - object ContractKeyNotFound - extends ErrorCode( - id = "CONTRACT_KEY_NOT_FOUND", - ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, - ) { - - case class Reject( - override val cause: String, - _key: GlobalKey, - )(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = cause - ) { - override def resources: Seq[(ErrorResource, String)] = Seq( - (ErrorResource.ContractKey, _key.toString()) + @Resolution("Inspect the reason given and correct your application.") + object InvalidField + extends ErrorCode(id = "INVALID_FIELD", ErrorCategory.InvalidIndependentOfSystemState) { + case class Reject(_reason: String)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = s"The submitted command has a field with invalid value: ${_reason}" ) - } - - } + } - @Explanation( - "The ledger configuration could not be retrieved. This could happen due to incomplete initialization of the participant or due to an internal system error." - ) - @Resolution("Contact the participant operator.") - object LedgerConfigurationNotFound - extends ErrorCode( - id = "LEDGER_CONFIGURATION_NOT_FOUND", - ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, + @Explanation( + "This error is emitted when a submitted ledger API command specifies an invalid deduplication period." + ) + @Resolution( + "Inspect the error message, adjust the value of the deduplication period or ask the participant operator to increase the maximum deduplication period." + ) + object InvalidDeduplicationPeriodField + extends ErrorCode( + id = "INVALID_DEDUPLICATION_PERIOD", + ErrorCategory.InvalidGivenCurrentSystemStateOther, + ) { + case class Reject(_reason: String, _maxDeduplicationDuration: Duration)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = s"The submitted command had an invalid deduplication period: ${_reason}" ) { - - case class Reject()(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = "The ledger configuration is not available." - ) + override def context: Map[String, String] = + super.context + ("max_deduplication_duration" -> _maxDeduplicationDuration.toString) } } - @Explanation("""This error occurs if the Daml transaction fails due to an authorization error. - |An authorization means that the Daml transaction computed a different set of required submitters than - |you have provided during the submission as `actAs` parties.""") - @Resolution("This error type occurs if there is an application error.") - object AuthorizationError + @Explanation("""The supplied offset could not be converted to a binary offset.""") + @Resolution("Ensure the offset is specified as a hexadecimal string.") + object NonHexOffset extends ErrorCode( - id = "DAML_AUTHORIZATION_ERROR", + id = "NON_HEXADECIMAL_OFFSET", ErrorCategory.InvalidIndependentOfSystemState, ) { - - case class Reject(override val cause: String)(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl( - cause = cause + case class Error( + fieldName: String, + offsetValue: String, + message: String, + )(implicit + override val loggingContext: ContextualizedErrorLogger + ) extends BaseError.Impl( + cause = + s"Offset in ${fieldName} not specified in hexadecimal: ${offsetValue}: ${message}" ) } } - @Explanation("""This error occurs if there was an unexpected error within the interpreter""") + @Explanation("""This error occurs if there was an unexpected error in the Ledger API.""") @Resolution("Contact support.") object InternalError extends ErrorCode( @@ -580,7 +500,6 @@ object LedgerApiErrors extends LedgerApiErrorGroup { ErrorCategory.SystemInternalAssumptionViolated, ) { - // TODO error codes: This is an internal error not related to the interpreter case class CommandTrackerInternalError( message: String )(implicit @@ -624,47 +543,68 @@ object LedgerApiErrors extends LedgerApiErrorGroup { ) extends LoggingTransactionErrorImpl( cause = s"Daml-Engine interpretation failed with internal error: ${where} / ${message}" ) - } - // The "NonHexOffset" error code is currently only used by canton, but should also be used by the ledger api services, - // e.g. the ApiParticipantPruningService when it receives a non-hex-offset or by the other services such as the - // transaction service that validate offsets using com.daml.ledger.api.validation.LedgerOffsetValidator.validate - @Explanation("""The supplied offset could not be converted to a binary offset.""") - @Resolution("Ensure the offset is specified as a hexadecimal string.") - object NonHexOffset - extends ErrorCode( - id = "NON_HEXADECIMAL_OFFSET", - ErrorCategory.InvalidIndependentOfSystemState, - ) { - case class Error( - fieldName: String, - offsetValue: String, - message: String, - )(implicit - override val loggingContext: ContextualizedErrorLogger - ) extends BaseError.Impl( - cause = s"Offset in ${fieldName} not specified in hexadecimal: ${offsetValue}: ${message}" - ) + case class VersionService(message: String)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl(cause = message) } - object VersionServiceError extends ErrorGroup { - @Explanation("This error occurs if there was an unexpected error within the version service.") - @Resolution("Contact support.") - object InternalError + object AdminServices { + @Explanation("This rejection is given when a new configuration is rejected.") + @Resolution("Fetch newest configuration and/or retry.") + object ConfigurationEntryRejected extends ErrorCode( - id = "VERSION_SERVICE_INTERNAL_ERROR", - ErrorCategory.SystemInternalAssumptionViolated, + id = "CONFIGURATION_ENTRY_REJECTED", + ErrorCategory.InvalidGivenCurrentSystemStateOther, ) { + case class Reject(message: String)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = message + ) + } + @Explanation("This rejection is given when a package upload is rejected.") + @Resolution("Refer to the detailed message of the received error.") + object PackageUploadRejected + extends ErrorCode( + id = "PACKAGE_UPLOAD_REJECTED", + ErrorCategory.InvalidGivenCurrentSystemStateOther, + ) { case class Reject(message: String)(implicit loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl(cause = message) + ) extends LoggingTransactionErrorImpl( + cause = message + ) + } + + @Explanation( + "This rejection is given when a request processing status is not known and a time-out is reached." + ) + @Resolution( + "Retry for transient problems. If non-transient contact the operator as the time-out limit might be too short." + ) + object RequestTimeOut + extends ErrorCode( + id = "REQUEST_TIME_OUT", + ErrorCategory.DeadlineExceededRequestStateUnknown, + ) { + case class Reject(message: String, override val definiteAnswer: Boolean)(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = message + ) } } - object CommandRejections extends ErrorGroup { - @Explanation("A command with the given command id has already been successfully processed") - @Resolution("Celebrate, as your command has already been delivered") + object ConsistencyErrors extends ErrorGroup { + @Explanation("A command with the given command id has already been successfully processed.") + @Resolution( + """The correct resolution depends on the use case. If the error received pertains to a submission retried due to a timeout, + |do nothing, as the previous command has already been accepted. + |If the intent is to submit a new command, re-submit using a distinct command id. + |""" + ) object DuplicateCommand extends ErrorCode( id = "DUPLICATE_COMMAND", @@ -693,55 +633,6 @@ object LedgerApiErrors extends LedgerApiErrorGroup { ) extends LoggingTransactionErrorImpl(cause = cause) } - @Explanation("The submitting party has not been allocated.") - @Resolution( - "Check that the party identifier is correct, allocate the submitting party, " + - "request its allocation or wait for it to be allocated before retrying the transaction submission." - ) - object SubmittingPartyNotKnownOnLedger - extends ErrorCode( - id = "SUBMITTING_PARTY_NOT_KNOWN_ON_LEDGER", - ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, // It may become known at a later time - ) { - case class Reject( - submitter_party: String - )(implicit loggingContext: ContextualizedErrorLogger) - extends LoggingTransactionErrorImpl( - cause = s"Party not known on ledger: Submitting party '$submitter_party' not known" - ) { - override def resources: Seq[(ErrorResource, String)] = Seq( - ErrorResource.Party -> submitter_party - ) - } - } - - @Explanation("One or more informee parties have not been allocated.") - @Resolution( - "Check that all the informee party identifiers are correct, allocate all the informee parties, " + - "request their allocation or wait for them to be allocated before retrying the transaction submission." - ) - object PartyNotKnownOnLedger - extends ErrorCode( - id = "PARTY_NOT_KNOWN_ON_LEDGER", - ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, - ) { - case class Reject(parties: Set[String])(implicit - loggingContext: ContextualizedErrorLogger - ) extends LoggingTransactionErrorImpl(cause = s"Parties not known on ledger: ${parties - .mkString("[", ",", "]")}") { - override def resources: Seq[(ErrorResource, String)] = - parties.map((ErrorResource.Party, _)).toSeq - } - - @deprecated - case class RejectDeprecated( - description: String - )(implicit loggingContext: ContextualizedErrorLogger) - extends LoggingTransactionErrorImpl( - cause = s"Party not known on ledger: $description" - ) - } - @Explanation("At least one input has been altered by a concurrent transaction submission.") @Resolution( "The correct resolution depends on the business flow, for example it may be possible to proceed " + @@ -761,13 +652,15 @@ object LedgerApiErrors extends LedgerApiErrorGroup { ) } - @Explanation("""This error occurs if the Daml engine interpreter can not find a referenced contract. This - |can be caused by either the contract not being known to the participant, or not being known to - |the submitting parties or already being archived.""") + @Explanation( + """This error occurs if the Daml engine can not find a referenced contract. This + |can be caused by either the contract not being known to the participant, or not being known to + |the submitting parties or already being archived.""" + ) @Resolution("This error type occurs if there is contention on a contract.") - object ContractsNotFound + object ContractNotFound extends ErrorCode( - id = "CONTRACTS_NOT_FOUND", + id = "CONTRACT_NOT_FOUND", ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, ) { @@ -780,6 +673,19 @@ object LedgerApiErrors extends LedgerApiErrorGroup { (ErrorResource.ContractId, notFoundContractIds.mkString("[", ", ", "]")) ) } + + case class Reject( + override val cause: String, + _cid: Value.ContractId, + )(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl( + cause = cause + ) { + override def resources: Seq[(ErrorResource, String)] = Seq( + (ErrorResource.ContractId, _cid.coid) + ) + } } @Explanation( @@ -825,6 +731,80 @@ object LedgerApiErrors extends LedgerApiErrorGroup { ) extends LoggingTransactionErrorImpl(cause = cause) } + @Explanation( + "The ledger time of the submission violated some constraint on the ledger time." + ) + @Resolution("Retry the transaction submission.") + object InvalidLedgerTime + extends ErrorCode( + id = "INVALID_LEDGER_TIME", + ErrorCategory.InvalidGivenCurrentSystemStateOther, // It may succeed at a later time + ) { + case class RejectEnriched( + details: String, + ledger_time: Instant, + ledger_time_lower_bound: Instant, + ledger_time_upper_bound: Instant, + )(implicit loggingContext: ContextualizedErrorLogger) + extends LoggingTransactionErrorImpl(cause = s"Invalid ledger time: $details") + + case class RejectSimple( + details: String + )(implicit loggingContext: ContextualizedErrorLogger) + extends LoggingTransactionErrorImpl(cause = s"Invalid ledger time: $details") + } + } + + object WriteServiceRejections extends ErrorGroup { + @Explanation("The submitting party has not been allocated.") + @Resolution( + "Check that the party identifier is correct, allocate the submitting party, " + + "request its allocation or wait for it to be allocated before retrying the transaction submission." + ) + object SubmittingPartyNotKnownOnLedger + extends ErrorCode( + id = "SUBMITTING_PARTY_NOT_KNOWN_ON_LEDGER", + ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, // It may become known at a later time + ) { + case class Reject( + submitter_party: String + )(implicit loggingContext: ContextualizedErrorLogger) + extends LoggingTransactionErrorImpl( + cause = s"Party not known on ledger: Submitting party '$submitter_party' not known" + ) { + override def resources: Seq[(ErrorResource, String)] = Seq( + ErrorResource.Party -> submitter_party + ) + } + } + + @Explanation("One or more informee parties have not been allocated.") + @Resolution( + "Check that all the informee party identifiers are correct, allocate all the informee parties, " + + "request their allocation or wait for them to be allocated before retrying the transaction submission." + ) + object PartyNotKnownOnLedger + extends ErrorCode( + id = "PARTY_NOT_KNOWN_ON_LEDGER", + ErrorCategory.InvalidGivenCurrentSystemStateResourceMissing, + ) { + case class Reject(parties: Set[String])(implicit + loggingContext: ContextualizedErrorLogger + ) extends LoggingTransactionErrorImpl(cause = s"Parties not known on ledger: ${parties + .mkString("[", ",", "]")}") { + override def resources: Seq[(ErrorResource, String)] = + parties.map((ErrorResource.Party, _)).toSeq + } + + @deprecated + case class RejectDeprecated( + description: String + )(implicit loggingContext: ContextualizedErrorLogger) + extends LoggingTransactionErrorImpl( + cause = s"Party not known on ledger: $description" + ) + } + @Explanation("An invalid transaction submission was not detected by the participant.") @Resolution("Contact support.") @deprecated("Corresponds to transaction submission rejections that are not produced anymore.") @@ -847,7 +827,9 @@ object LedgerApiErrors extends LedgerApiErrorGroup { @Explanation( "The Participant node did not have sufficient resource quota to submit the transaction." ) - @Resolution("Inspect the error message and retry after after correcting the underlying issue.") + @Resolution( + "Inspect the error message and retry after after correcting the underlying issue." + ) @deprecated("Corresponds to transaction submission rejections that are not produced anymore.") @DeprecatedDocs( "Corresponds to transaction submission rejections that are not produced anymore." @@ -873,28 +855,5 @@ object LedgerApiErrors extends LedgerApiErrorGroup { )(implicit loggingContext: ContextualizedErrorLogger) extends LoggingTransactionErrorImpl(cause = s"Inconsistent: $details") } - - @Explanation( - "The ledger time of the submission violated some constraint on the ledger time." - ) - @Resolution("Retry the transaction submission.") - object InvalidLedgerTime - extends ErrorCode( - id = "INVALID_LEDGER_TIME", - ErrorCategory.InvalidGivenCurrentSystemStateOther, // It may succeed at a later time - ) { - case class RejectEnriched( - details: String, - ledger_time: Instant, - ledger_time_lower_bound: Instant, - ledger_time_upper_bound: Instant, - )(implicit loggingContext: ContextualizedErrorLogger) - extends LoggingTransactionErrorImpl(cause = s"Invalid ledger time: $details") - - case class RejectSimple( - details: String - )(implicit loggingContext: ContextualizedErrorLogger) - extends LoggingTransactionErrorImpl(cause = s"Invalid ledger time: $details") - } } } diff --git a/ledger/error/src/main/scala/com/daml/error/definitions/PackageServiceError.scala b/ledger/error/src/main/scala/com/daml/error/definitions/PackageServiceError.scala index 42ba4ce7756e..d80de019cfa3 100644 --- a/ledger/error/src/main/scala/com/daml/error/definitions/PackageServiceError.scala +++ b/ledger/error/src/main/scala/com/daml/error/definitions/PackageServiceError.scala @@ -3,16 +3,7 @@ package com.daml.error.definitions -import com.daml.error.{ - BaseError, - ContextualizedErrorLogger, - ErrorCategory, - ErrorCode, - ErrorGroup, - Explanation, - Resolution, -} -import com.daml.error.definitions.ErrorGroups.ParticipantErrorGroup.PackageServiceErrorGroup +import com.daml.error._ import com.daml.lf.archive.{Error => LfArchiveError} import com.daml.lf.data.Ref import com.daml.lf.data.Ref.PackageId @@ -27,10 +18,8 @@ abstract class PackageServiceError( final override def logOnCreation: Boolean = true } -object PackageServiceError extends PackageServiceErrorGroup { - +object PackageServiceError extends LedgerApiErrors.PackageServiceErrorGroup { object Reading extends ErrorGroup { - @Explanation( """This error indicates that the supplied dar file name did not meet the requirements to be stored in the persistence store.""" ) @@ -203,9 +192,11 @@ object PackageServiceError extends PackageServiceErrorGroup { )(implicit val loggingContext: ContextualizedErrorLogger ) extends PackageServiceError( - cause = LedgerApiErrors.Package.AllowedLanguageVersions + cause = LedgerApiErrors.CommandExecution.Package.AllowedLanguageVersions .buildCause(packageId, languageVersion, allowedLanguageVersions) - )(LedgerApiErrors.Package.AllowedLanguageVersions) // reuse error code of ledger api server + )( + LedgerApiErrors.CommandExecution.Package.AllowedLanguageVersions + ) // reuse error code of ledger api server @Explanation( """This error indicates that the uploaded Dar is broken because it is missing internal dependencies.""" diff --git a/ledger/error/src/main/scala/com/daml/error/definitions/PruningServiceError.scala b/ledger/error/src/main/scala/com/daml/error/definitions/PruningServiceError.scala deleted file mode 100644 index f7e3d6e49dd3..000000000000 --- a/ledger/error/src/main/scala/com/daml/error/definitions/PruningServiceError.scala +++ /dev/null @@ -1,25 +0,0 @@ -// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.daml.error.definitions - -import com.daml.error._ -import com.daml.error.definitions.ErrorGroups.ParticipantErrorGroup.PruningServiceErrorGroup - -trait PruningServiceError extends BaseError -object PruningServiceError extends PruningServiceErrorGroup { - @Explanation("""Pruning has failed because of an internal server error.""") - @Resolution("Identify the error in the server log.") - object InternalServerError - extends ErrorCode( - id = "INTERNAL_PRUNING_ERROR", - ErrorCategory.SystemInternalAssumptionViolated, - ) { - final case class Error(reason: String)(implicit - val loggingContext: ContextualizedErrorLogger - ) extends BaseError.Impl( - cause = "Internal error such as the inability to write to the database" - ) - with PruningServiceError - } -} diff --git a/ledger/error/src/main/scala/com/daml/error/definitions/RejectionGenerators.scala b/ledger/error/src/main/scala/com/daml/error/definitions/RejectionGenerators.scala index 90ec06007be1..3ab8bf282374 100644 --- a/ledger/error/src/main/scala/com/daml/error/definitions/RejectionGenerators.scala +++ b/ledger/error/src/main/scala/com/daml/error/definitions/RejectionGenerators.scala @@ -12,12 +12,13 @@ import io.grpc.StatusRuntimeException import io.grpc.protobuf.StatusProto class RejectionGenerators(conformanceMode: Boolean) { + // TODO error codes: Remove conformance mode private val adjustErrors = Map( - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound -> Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.ContractNotActive -> Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound -> Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound -> Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.GenericInterpretationError -> Code.INVALID_ARGUMENT, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound -> Code.INVALID_ARGUMENT, + LedgerApiErrors.CommandExecution.Interpreter.ContractNotActive -> Code.INVALID_ARGUMENT, + LedgerApiErrors.ConsistencyErrors.ContractNotFound -> Code.ABORTED, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound -> Code.INVALID_ARGUMENT, + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError -> Code.INVALID_ARGUMENT, ) private def enforceConformance(ex: StatusRuntimeException): StatusRuntimeException = @@ -53,11 +54,13 @@ class RejectionGenerators(conformanceMode: Boolean) { def processPackageError(err: LfError.Package.Error): BaseError = err match { case e: Package.Internal => LedgerApiErrors.InternalError.PackageInternal(e) case Package.Validation(validationError) => - LedgerApiErrors.Package.PackageValidationFailed.Reject(validationError.pretty) + LedgerApiErrors.CommandExecution.Package.PackageValidationFailed + .Reject(validationError.pretty) case Package.MissingPackage(packageId, context) => - LedgerApiErrors.Package.MissingPackage.Reject(packageId, context) + LedgerApiErrors.RequestValidation.NotFound.Package + .InterpretationReject(packageId, context) case Package.AllowedLanguageVersion(packageId, languageVersion, allowedLanguageVersions) => - LedgerApiErrors.Package.AllowedLanguageVersions.Error( + LedgerApiErrors.CommandExecution.Package.AllowedLanguageVersions.Error( packageId, languageVersion, allowedLanguageVersions, @@ -68,7 +71,7 @@ class RejectionGenerators(conformanceMode: Boolean) { def processPreprocessingError(err: LfError.Preprocessing.Error): BaseError = err match { case e: Preprocessing.Internal => LedgerApiErrors.InternalError.Preprocessing(e) - case e => LedgerApiErrors.PreprocessingErrors.PreprocessingFailed.Reject(e) + case e => LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed.Reject(e) } def processValidationError(err: LfError.Validation.Error): BaseError = err match { @@ -85,56 +88,68 @@ class RejectionGenerators(conformanceMode: Boolean) { err match { case LfInterpretationError.ContractNotFound(cid) => - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound + LedgerApiErrors.ConsistencyErrors.ContractNotFound .Reject(renderedMessage, cid) case LfInterpretationError.ContractKeyNotFound(key) => - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound .Reject(renderedMessage, key) case _: LfInterpretationError.FailedAuthorization => - LedgerApiErrors.InterpreterErrors.AuthorizationError.Reject(renderedMessage) + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError + .Reject(renderedMessage) case e: LfInterpretationError.ContractNotActive => - LedgerApiErrors.InterpreterErrors.ContractNotActive.Reject(renderedMessage, e) + LedgerApiErrors.CommandExecution.Interpreter.ContractNotActive + .Reject(renderedMessage, e) case _: LfInterpretationError.LocalContractKeyNotVisible => - LedgerApiErrors.InterpreterErrors.GenericInterpretationError.Error(renderedMessage) + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError + .Error(renderedMessage) case LfInterpretationError.DuplicateContractKey(key) => - LedgerApiErrors.CommandRejections.DuplicateContractKey + LedgerApiErrors.ConsistencyErrors.DuplicateContractKey .InterpretationReject(renderedMessage, key) case _: LfInterpretationError.UnhandledException => - LedgerApiErrors.InterpreterErrors.GenericInterpretationError.Error( + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError.Error( renderedMessage + detailMessage.fold("")(x => ". Details: " + x) ) case _: LfInterpretationError.UserError => - LedgerApiErrors.InterpreterErrors.GenericInterpretationError.Error(renderedMessage) + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError + .Error(renderedMessage) case _: LfInterpretationError.TemplatePreconditionViolated => - LedgerApiErrors.InterpreterErrors.GenericInterpretationError.Error(renderedMessage) + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError + .Error(renderedMessage) case _: LfInterpretationError.CreateEmptyContractKeyMaintainers => - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError.Error( - renderedMessage - ) + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError + .Error( + renderedMessage + ) case _: LfInterpretationError.FetchEmptyContractKeyMaintainers => - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError.Error( - renderedMessage - ) + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError + .Error( + renderedMessage + ) case _: LfInterpretationError.WronglyTypedContract => - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError.Error( - renderedMessage - ) + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError + .Error( + renderedMessage + ) case LfInterpretationError.NonComparableValues => - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError.Error( - renderedMessage - ) + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError + .Error( + renderedMessage + ) case _: LfInterpretationError.ContractIdInContractKey => - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError.Error( - renderedMessage - ) + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError + .Error( + renderedMessage + ) case LfInterpretationError.ValueExceedsMaxNesting => - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError.Error( - renderedMessage - ) + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError + .Error( + renderedMessage + ) case _: LfInterpretationError.ContractIdComparability => - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError.Error( - renderedMessage - ) + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError + .Error( + renderedMessage + ) } } @@ -160,7 +175,7 @@ class RejectionGenerators(conformanceMode: Boolean) { if e.message.contains( "requires authorizers" ) => // Keeping this around as a string match as daml is not yet generating LfError.InterpreterErrors.Validation - LedgerApiErrors.InterpreterErrors.AuthorizationError.Reject(e.message) + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError.Reject(e.message) } toGrpc(transformed) } @@ -168,34 +183,10 @@ class RejectionGenerators(conformanceMode: Boolean) { cause match { case ErrorCauseExport.DamlLf(error) => processLfError(error) case x: ErrorCauseExport.LedgerTime => - toGrpc(LedgerApiErrors.CommandPreparation.FailedToDetermineLedgerTime.Reject(x.explain)) - } - } - - // TODO error codes: This converter is deprecated and should be removed - // Instead of using this, construct proper validation errors in callers of this method - // and only convert to StatusRuntimeExceptions when dispatched (e.g. in ApiSubmissionService) - def validationFailure(reject: StatusRuntimeException)(implicit - contextualizedErrorLogger: ContextualizedErrorLogger - ): StatusRuntimeException = { - val description = reject.getStatus.getDescription - reject.getStatus.getCode match { - case Code.INVALID_ARGUMENT => - if (description.startsWith("Missing field:")) { - toGrpc(LedgerApiErrors.CommandValidation.MissingField.Reject(description)) - } else if (description.startsWith("Invalid argument:")) { - toGrpc(LedgerApiErrors.CommandValidation.InvalidArgument.Reject(description)) - } else if (description.startsWith("Invalid field:")) { - toGrpc(LedgerApiErrors.CommandValidation.InvalidField.Reject(description)) - } else { - contextualizedErrorLogger.warn(s"Unknown invalid argument rejection: ${reject.getStatus}") - reject - } - case Code.NOT_FOUND if description.startsWith("Ledger ID") => - toGrpc(LedgerApiErrors.CommandValidation.LedgerIdMismatch.Reject(description)) - case _ => - contextualizedErrorLogger.warn(s"Unknown rejection: ${reject.getStatus}") - reject + toGrpc( + LedgerApiErrors.CommandExecution.FailedToDetermineLedgerTime + .Reject(x.explain) + ) } } } diff --git a/ledger/error/src/main/scala/com/daml/error/definitions/SubmissionErrors.scala b/ledger/error/src/main/scala/com/daml/error/definitions/SubmissionErrors.scala deleted file mode 100644 index 1d58b92dccb4..000000000000 --- a/ledger/error/src/main/scala/com/daml/error/definitions/SubmissionErrors.scala +++ /dev/null @@ -1,58 +0,0 @@ -// Copyright (c) 2021 Digital Asset (Switzerland) GmbH and/or its affiliates. All rights reserved. -// SPDX-License-Identifier: Apache-2.0 - -package com.daml.error.definitions - -import com.daml.error.definitions.ErrorGroups.ParticipantErrorGroup.TransactionErrorGroup.SubmissionErrorGroup -import com.daml.error.{ErrorCategory, ErrorCode, Explanation, Resolution} -import org.slf4j.event.Level - -object SubmissionErrors extends SubmissionErrorGroup { - - // TODO(i5990) split the text into sub-categories with codes - @Explanation("""This error has not yet been properly categorised into sub-error codes.""") - object MalformedRequest - extends ErrorCode( - id = "MALFORMED_REQUEST", - ErrorCategory.InvalidIndependentOfSystemState, - ) { - - // TODO error codes: properly set `definiteAnswer` where appropriate when sub-categories are created - case class Error(message: String) extends TransactionErrorImpl(cause = "Malformed request") - } - - @Explanation( - """This error occurs when the participant rejects a command due to excessive load. - |Load can be caused as follows: - |1. when commands are submitted to the participant through its ledger api, - |2. when the participant receives requests from other participants through a connected domain.""" - ) - @Resolution( - """Wait a bit and retry, preferably with some backoff factor. - |If possible, ask other participants to send fewer requests; the domain operator can enforce this by imposing a rate limit.""" - ) - object ParticipantBackpressure - extends ErrorCode( - id = "PARTICIPANT_BACKPRESSURE", - ErrorCategory.ContentionOnSharedResources, - ) { - override def logLevel: Level = Level.WARN - - case class Rejection(reason: String) - extends TransactionErrorImpl(cause = "The participant is overloaded") - } - - @Explanation( - """This error occurs when a command is submitted while the system is performing a shutdown.""" - ) - @Resolution( - "Assuming that the participant will restart or failover eventually, retry in a couple of seconds." - ) - object SubmissionDuringShutdown - extends ErrorCode( - id = "SUBMISSION_DURING_SHUTDOWN", - ErrorCategory.ContentionOnSharedResources, - ) { - case class Rejection() extends TransactionErrorImpl(cause = "Command rejected due to shutdown.") - } -} diff --git a/ledger/ledger-api-common/src/main/scala/com/digitalasset/ledger/api/validation/LedgerOffsetValidator.scala b/ledger/ledger-api-common/src/main/scala/com/digitalasset/ledger/api/validation/LedgerOffsetValidator.scala index d2039e669437..c3f8e27c7abe 100644 --- a/ledger/ledger-api-common/src/main/scala/com/digitalasset/ledger/api/validation/LedgerOffsetValidator.scala +++ b/ledger/ledger-api-common/src/main/scala/com/digitalasset/ledger/api/validation/LedgerOffsetValidator.scala @@ -18,7 +18,7 @@ class LedgerOffsetValidator(errorFactories: ErrorFactories) { private val fieldValidations = FieldValidations(errorFactories) - import errorFactories.{invalidArgument, missingField, offsetOutOfRange} + import errorFactories.{invalidArgument, missingField, offsetAfterLedgerEnd} import fieldValidations.requireLedgerString def validateOptional( @@ -58,11 +58,7 @@ class LedgerOffsetValidator(errorFactories: ErrorFactories) { ): Either[StatusRuntimeException, Unit] = ledgerOffset match { case abs: domain.LedgerOffset.Absolute if abs > ledgerEnd => - Left( - offsetOutOfRange( - s"$offsetType offset ${abs.value} is after ledger end ${ledgerEnd.value}" - ) - ) + Left(offsetAfterLedgerEnd(offsetType, abs.value, ledgerEnd.value)) case _ => Right(()) } 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 2a9a131bd1b8..bad32b6b9498 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 @@ -27,6 +27,7 @@ import scalaz.syntax.tag._ import java.sql.{SQLNonTransientException, SQLTransientException} import java.time.Duration +import scala.annotation.nowarn class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitcher) { def sqlTransientException(exception: SQLTransientException)(implicit @@ -50,35 +51,19 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch .setMessage("Transaction not found, or not visible.") .build() ), - v2 = LedgerApiErrors.ReadErrors.TransactionNotFound + v2 = LedgerApiErrors.RequestValidation.NotFound.Transaction .Reject(transactionId) .asGrpcError, ) - def malformedPackageId[Request](message: String)(implicit - contextualizedErrorLogger: ContextualizedErrorLogger - ): StatusRuntimeException = - errorCodesVersionSwitcher.choose( - v1 = grpcError( - Status - .newBuilder() - .setCode(Code.INVALID_ARGUMENT.value()) - .setMessage(message) - .build() - ), - v2 = LedgerApiErrors.ReadErrors.MalformedPackageId - .Reject( - message = message - ) - .asGrpcError, - ) - def packageNotFound(packageId: String)(implicit contextualizedErrorLogger: ContextualizedErrorLogger ): StatusRuntimeException = errorCodesVersionSwitcher.choose( v1 = io.grpc.Status.NOT_FOUND.asRuntimeException(), - v2 = LedgerApiErrors.ReadErrors.PackageNotFound.Reject(packageId = packageId).asGrpcError, + v2 = LedgerApiErrors.RequestValidation.NotFound.Package + .Reject(packageId = packageId) + .asGrpcError, ) def versionServiceInternalError(message: String)(implicit @@ -92,7 +77,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch .setMessage(message) .build() ), - v2 = LedgerApiErrors.VersionServiceError.InternalError.Reject(message).asGrpcError, + v2 = LedgerApiErrors.InternalError.VersionService(message).asGrpcError, ) def duplicateCommandException(implicit @@ -111,7 +96,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch contextualizedErrorLogger.info(exception.getMessage) exception }, - v2 = LedgerApiErrors.CommandRejections.DuplicateCommand.Reject().asGrpcError, + v2 = LedgerApiErrors.ConsistencyErrors.DuplicateCommand.Reject().asGrpcError, ) /** @param expected Expected ledger id. @@ -136,7 +121,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch addDefiniteAnswerDetails(definiteAnswer, statusBuilder) grpcError(statusBuilder.build()) }, - v2 = LedgerApiErrors.CommandValidation.LedgerIdMismatch + v2 = LedgerApiErrors.RequestValidation.LedgerIdMismatch .Reject( s"Ledger ID '${received.unwrap}' not found. Actual Ledger ID is '${expected.unwrap}'." ) @@ -160,7 +145,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch addDefiniteAnswerDetails(definiteAnswer, statusBuilder) grpcError(statusBuilder.build()) }, - v2 = LedgerApiErrors.CommandValidation.MissingField + v2 = LedgerApiErrors.RequestValidation.MissingField .Reject(fieldName) .asGrpcError, ) @@ -174,9 +159,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch ): StatusRuntimeException = errorCodesVersionSwitcher.choose( v1 = invalidArgumentV1(definiteAnswer, message), - // 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 + v2 = LedgerApiErrors.RequestValidation.InvalidArgument .Reject(message) .asGrpcError, ) @@ -194,26 +177,40 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch addDefiniteAnswerDetails(definiteAnswer, statusBuilder) grpcError(statusBuilder.build()) }, - // TODO error codes: Revisit this error: 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, GrpcHealthService). - v2 = LedgerApiErrors.CommandValidation.InvalidArgument + v2 = LedgerApiErrors.RequestValidation.InvalidArgument .Reject(message) .asGrpcError, ) - // TODO error codes: Reconcile with com.daml.platform.server.api.validation.ErrorFactories.offsetOutOfRange - def offsetOutOfRange_was_invalidArgument( + def offsetOutOfRange( definiteAnswer: Option[Boolean] )(message: String)(implicit contextualizedErrorLogger: ContextualizedErrorLogger ): StatusRuntimeException = errorCodesVersionSwitcher.choose( v1 = invalidArgumentV1(definiteAnswer, message), - v2 = LedgerApiErrors.ReadErrors.RequestedOffsetOutOfRange + v2 = LedgerApiErrors.RequestValidation.OffsetOutOfRange .Reject(message) .asGrpcError, ) + def offsetAfterLedgerEnd(offsetType: String, requestedOffset: String, ledgerEnd: String)(implicit + contextualizedErrorLogger: ContextualizedErrorLogger + ): StatusRuntimeException = { + errorCodesVersionSwitcher.choose( + v1 = grpcError( + Status + .newBuilder() + .setCode(Code.OUT_OF_RANGE.value()) + .setMessage(s"$offsetType offset ($requestedOffset) is after ledger end ($ledgerEnd)") + .build() + ), + v2 = LedgerApiErrors.RequestValidation.OffsetAfterLedgerEnd + .Reject(offsetType, requestedOffset, ledgerEnd) + .asGrpcError, + ) + } + def nonHexOffset( definiteAnswer: Option[Boolean] )(fieldName: String, offsetValue: String, message: String)(implicit @@ -221,7 +218,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch ): StatusRuntimeException = errorCodesVersionSwitcher.choose( v1 = invalidArgumentV1(definiteAnswer, message), - v2 = LedgerApiErrors.NonHexOffset + v2 = LedgerApiErrors.RequestValidation.NonHexOffset .Error( fieldName = fieldName, offsetValue = offsetValue, @@ -238,7 +235,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch )(implicit contextualizedErrorLogger: ContextualizedErrorLogger): StatusRuntimeException = errorCodesVersionSwitcher.choose( legacyInvalidField(fieldName, message, definiteAnswer), - LedgerApiErrors.CommandValidation.InvalidDeduplicationPeriodField + LedgerApiErrors.RequestValidation.InvalidDeduplicationPeriodField .Reject(message, maxDeduplicationDuration) .asGrpcError, ) @@ -255,13 +252,13 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch )(implicit contextualizedErrorLogger: ContextualizedErrorLogger): StatusRuntimeException = errorCodesVersionSwitcher.choose( v1 = legacyInvalidField(fieldName, message, definiteAnswer), - v2 = ledgerCommandValidationInvalidField(fieldName, message).asGrpcError, + v2 = ledgerRequestValidationInvalidField(fieldName, message).asGrpcError, ) - private def ledgerCommandValidationInvalidField(fieldName: String, message: String)(implicit + private def ledgerRequestValidationInvalidField(fieldName: String, message: String)(implicit contextualizedErrorLogger: ContextualizedErrorLogger - ): LedgerApiErrors.CommandValidation.InvalidField.Reject = { - LedgerApiErrors.CommandValidation.InvalidField + ): LedgerApiErrors.RequestValidation.InvalidField.Reject = { + LedgerApiErrors.RequestValidation.InvalidField .Reject(s"Invalid field $fieldName: $message") } @@ -278,28 +275,12 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch grpcError(statusBuilder.build()) } - def offsetOutOfRange(description: String)(implicit - contextualizedErrorLogger: ContextualizedErrorLogger - ): StatusRuntimeException = - // TODO error codes: Pass the offsets as arguments to this method and build the description here - errorCodesVersionSwitcher.choose( - v1 = grpcError( - Status - .newBuilder() - .setCode(Code.OUT_OF_RANGE.value()) - .setMessage(description) - .build() - ), - v2 = LedgerApiErrors.ReadErrors.RequestedOffsetOutOfRange.Reject(description).asGrpcError, - ) - /** @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. * @return An exception with the [[Code.ABORTED]] status code. */ + @deprecated def aborted(message: String, definiteAnswer: Option[Boolean]): StatusRuntimeException = { - // TODO error codes: This error code is not specific enough. - // Break down into more specific errors. val statusBuilder = Status .newBuilder() .setCode(Code.ABORTED.value()) @@ -308,12 +289,13 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch grpcError(statusBuilder.build()) } + @nowarn("msg=deprecated") def isTimeoutUnknown_wasAborted(message: String, definiteAnswer: Option[Boolean])(implicit contextualizedErrorLogger: ContextualizedErrorLogger ): StatusRuntimeException = { errorCodesVersionSwitcher.choose( v1 = aborted(message, definiteAnswer), - v2 = LedgerApiErrors.WriteErrors.RequestTimeOut + v2 = LedgerApiErrors.AdminServices.RequestTimeOut .Reject( message, // TODO error codes: How to handle None definiteAnswer? @@ -328,16 +310,17 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch ): StatusRuntimeException = { errorCodesVersionSwitcher.choose( v1 = invalidArgumentV1(definiteAnswer, message), - v2 = LedgerApiErrors.WriteErrors.PackageUploadRejected.Reject(message).asGrpcError, + v2 = LedgerApiErrors.AdminServices.PackageUploadRejected.Reject(message).asGrpcError, ) } + @nowarn("msg=deprecated") def configurationEntryRejected(message: String, definiteAnswer: Option[Boolean])(implicit contextualizedErrorLogger: ContextualizedErrorLogger ): StatusRuntimeException = { errorCodesVersionSwitcher.choose( v1 = aborted(message, definiteAnswer), - v2 = LedgerApiErrors.WriteErrors.ConfigurationEntryRejected.Reject(message).asGrpcError, + v2 = LedgerApiErrors.AdminServices.ConfigurationEntryRejected.Reject(message).asGrpcError, ) } @@ -388,41 +371,25 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch /** @param definiteAnswer A flag that says whether it is a definite answer. Provided only in the context of command deduplication. * @return An exception with the [[Code.UNAVAILABLE]] status code. */ - def missingLedgerConfig(definiteAnswer: Option[Boolean])(implicit + def missingLedgerConfig( + legacyGrpcStatusCode: io.grpc.Status.Code + )(definiteAnswer: Option[Boolean])(implicit contextualizedErrorLogger: ContextualizedErrorLogger ): StatusRuntimeException = errorCodesVersionSwitcher.choose( v1 = { val statusBuilder = Status .newBuilder() - .setCode(Code.UNAVAILABLE.value()) + .setCode(legacyGrpcStatusCode.value()) .setMessage("The ledger configuration is not available.") 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 Daml interpreter. - v2 = LedgerApiErrors.InterpreterErrors.LookupErrors.LedgerConfigurationNotFound + v2 = LedgerApiErrors.RequestValidation.NotFound.LedgerConfiguration .Reject() .asGrpcError, ) - // TODO error codes: Duplicate of missingLedgerConfig - def missingLedgerConfigUponRequest(implicit - contextualizedErrorLogger: ContextualizedErrorLogger - ): StatusRuntimeException = errorCodesVersionSwitcher.choose( - v1 = grpcError( - Status - .newBuilder() - .setCode(Code.NOT_FOUND.value()) - .setMessage("The ledger configuration is not available.") - .build() - ), - v2 = LedgerApiErrors.InterpreterErrors.LookupErrors.LedgerConfigurationNotFound - .Reject() - .asGrpcError, - ) - def participantPrunedDataAccessed(message: String)(implicit contextualizedErrorLogger: ContextualizedErrorLogger ): StatusRuntimeException = @@ -434,13 +401,15 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch .setMessage(message) .build() ), - v2 = LedgerApiErrors.ReadErrors.ParticipantPrunedDataAccessed.Reject(message).asGrpcError, + v2 = LedgerApiErrors.RequestValidation.ParticipantPrunedDataAccessed + .Reject(message) + .asGrpcError, ) /** @param definiteAnswer A flag that says whether it is a definite answer. Provided only in the context of command deduplication. * @return An exception with the [[Code.UNAVAILABLE]] status code. */ - def serviceNotRunning(definiteAnswer: Option[Boolean])(implicit + def serviceNotRunning(serviceName: String)(definiteAnswer: Option[Boolean])(implicit contextualizedErrorLogger: ContextualizedErrorLogger ): StatusRuntimeException = errorCodesVersionSwitcher.choose( @@ -448,12 +417,11 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch val statusBuilder = Status .newBuilder() .setCode(Code.UNAVAILABLE.value()) - .setMessage("Service has been shut down.") + .setMessage(s"$serviceName has been shut down.") addDefiniteAnswerDetails(definiteAnswer, statusBuilder) grpcError(statusBuilder.build()) }, - // TODO error codes: Add service name to the error cause - v2 = LedgerApiErrors.ServiceNotRunning.Reject().asGrpcError, + v2 = LedgerApiErrors.ServiceNotRunning.Reject(serviceName).asGrpcError, ) def trackerFailure(msg: String)(implicit @@ -517,7 +485,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch v1 = RpcStatus .of(Code.INVALID_ARGUMENT.value(), s"Parties not known on ledger: $reason", Seq.empty), v2 = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.PartyNotKnownOnLedger + LedgerApiErrors.WriteServiceRejections.PartyNotKnownOnLedger .RejectDeprecated(reason) .asGrpcStatusFromContext ), @@ -533,7 +501,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch Seq.empty, ), v2 = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.ContractsNotFound + LedgerApiErrors.ConsistencyErrors.ContractNotFound .MultipleContractsNotFound(missingContractIds) .asGrpcStatusFromContext ), @@ -552,7 +520,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch Seq.empty, ), v2 = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.InconsistentContractKey + LedgerApiErrors.ConsistencyErrors.InconsistentContractKey .Reject( s"Contract key lookup with different results: expected [$lookupResult], actual [$currentResult]" ) @@ -566,7 +534,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch errorCodesVersionSwitcher.choose( v1 = RpcStatus.of(Code.ABORTED.value(), s"Inconsistent: $reason", Seq.empty), v2 = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.DuplicateContractKey + LedgerApiErrors.ConsistencyErrors.DuplicateContractKey .InterpretationReject(reason, key) .asGrpcStatusFromContext ), @@ -583,7 +551,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch Seq.empty, ), v2 = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.PartyNotKnownOnLedger + LedgerApiErrors.WriteServiceRejections.PartyNotKnownOnLedger .Reject(parties) .asGrpcStatusFromContext ), @@ -599,7 +567,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch Seq.empty, ), v2 = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.SubmitterCannotActViaParticipant + LedgerApiErrors.WriteServiceRejections.SubmitterCannotActViaParticipant .Reject(reason) .asGrpcStatusFromContext ), @@ -611,7 +579,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch errorCodesVersionSwitcher.choose( v1 = RpcStatus.of(Code.ABORTED.value(), s"Invalid ledger time: $reason", Seq.empty), v2 = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.InvalidLedgerTime + LedgerApiErrors.ConsistencyErrors.InvalidLedgerTime .RejectSimple(reason) .asGrpcStatusFromContext ), @@ -623,7 +591,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch errorCodesVersionSwitcher.choose( v1 = RpcStatus.of(Code.ABORTED.value(), s"Inconsistent: $reason", Seq.empty), v2 = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.Inconsistent.Reject(reason).asGrpcStatusFromContext + LedgerApiErrors.ConsistencyErrors.Inconsistent.Reject(reason).asGrpcStatusFromContext ), ) @@ -635,7 +603,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch errorCodesVersionSwitcher.choose( v1 = RpcStatus.of(Code.INVALID_ARGUMENT.value(), s"Disputed: $reason", Seq.empty), v2 = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.Disputed.Reject(reason).asGrpcStatusFromContext + LedgerApiErrors.WriteServiceRejections.Disputed.Reject(reason).asGrpcStatusFromContext ), ) @@ -646,7 +614,7 @@ class ErrorFactories private (errorCodesVersionSwitcher: ErrorCodesVersionSwitch errorCodesVersionSwitcher.choose( v1 = RpcStatus.of(Code.ABORTED.value(), s"Resources exhausted: $reason", Seq.empty), v2 = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.OutOfQuota.Reject(reason).asGrpcStatusFromContext + LedgerApiErrors.WriteServiceRejections.OutOfQuota.Reject(reason).asGrpcStatusFromContext ), ) } diff --git a/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/FieldValidations.scala b/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/FieldValidations.scala index bf77612ec907..00984ae5b76e 100644 --- a/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/FieldValidations.scala +++ b/ledger/ledger-api-common/src/main/scala/com/digitalasset/platform/server/api/validation/FieldValidations.scala @@ -4,7 +4,6 @@ package com.daml.platform.server.api.validation import java.time.Duration - import com.daml.api.util.DurationConversion import com.daml.error.ContextualizedErrorLogger import com.daml.ledger.api.domain.LedgerId @@ -15,7 +14,7 @@ import com.daml.lf.data.Ref import com.daml.lf.data.Ref.Party import com.daml.lf.value.Value.ContractId import com.google.protobuf.duration.{Duration => DurationProto} -import io.grpc.StatusRuntimeException +import io.grpc.{Status, StatusRuntimeException} // TODO error codes: Remove default usage of ErrorFactories class FieldValidations private (errorFactories: ErrorFactories) { @@ -151,7 +150,7 @@ class FieldValidations private (errorFactories: ErrorFactories) { ): Either[StatusRuntimeException, DeduplicationPeriod] = { optMaxDeduplicationDuration.fold[Either[StatusRuntimeException, DeduplicationPeriod]]( - Left(missingLedgerConfig(definiteAnswer = Some(false))) + Left(missingLedgerConfig(Status.Code.UNAVAILABLE)(definiteAnswer = Some(false))) )(maxDeduplicationDuration => { def validateDuration(duration: Duration, exceedsMaxDurationMessage: String) = { if (duration.isNegative) diff --git a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/CompletionServiceRequestValidatorTest.scala b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/CompletionServiceRequestValidatorTest.scala index 1ac94673e2fc..99b91c798d34 100644 --- a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/CompletionServiceRequestValidatorTest.scala +++ b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/CompletionServiceRequestValidatorTest.scala @@ -116,10 +116,10 @@ class CompletionServiceRequestValidatorTest ledgerEnd, ), expectedCodeV1 = OUT_OF_RANGE, - expectedDescriptionV1 = "Begin offset 1001 is after ledger end 1000", + expectedDescriptionV1 = "Begin offset (1001) is after ledger end (1000)", expectedCodeV2 = OUT_OF_RANGE, expectedDescriptionV2 = - "REQUESTED_OFFSET_OUT_OF_RANGE(12,0): Begin offset 1001 is after ledger end 1000", + "OFFSET_AFTER_LEDGER_END(12,0): Begin offset (1001) is after ledger end (1000)", ) } diff --git a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/SubmitRequestValidatorTest.scala b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/SubmitRequestValidatorTest.scala index d97abcb9ec80..79a20a082179 100644 --- a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/SubmitRequestValidatorTest.scala +++ b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/SubmitRequestValidatorTest.scala @@ -448,7 +448,7 @@ class SubmitRequestValidatorTest expectedDescriptionV1 = "The ledger configuration is not available.", expectedCodeV2 = NOT_FOUND, expectedDescriptionV2 = - "LEDGER_CONFIGURATION_NOT_FOUND(11,0): The ledger configuration is not available.", + "LEDGER_CONFIGURATION_NOT_FOUND(11,0): The ledger configuration could not be retrieved.", ) } } diff --git a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/TransactionServiceRequestValidatorTest.scala b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/TransactionServiceRequestValidatorTest.scala index 0bdc1e257870..d473a8ce9a10 100644 --- a/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/TransactionServiceRequestValidatorTest.scala +++ b/ledger/ledger-api-common/src/test/suite/scala/com/digitalasset/ledger/api/validation/TransactionServiceRequestValidatorTest.scala @@ -199,10 +199,10 @@ class TransactionServiceRequestValidatorTest ledgerEnd, ), expectedCodeV1 = OUT_OF_RANGE, - expectedDescriptionV1 = "Begin offset 1001 is after ledger end 1000", + expectedDescriptionV1 = "Begin offset (1001) is after ledger end (1000)", expectedCodeV2 = OUT_OF_RANGE, expectedDescriptionV2 = - "REQUESTED_OFFSET_OUT_OF_RANGE(12,0): Begin offset 1001 is after ledger end 1000", + "OFFSET_AFTER_LEDGER_END(12,0): Begin offset (1001) is after ledger end (1000)", ) } @@ -215,10 +215,10 @@ class TransactionServiceRequestValidatorTest ledgerEnd, ), expectedCodeV1 = OUT_OF_RANGE, - expectedDescriptionV1 = "End offset 1001 is after ledger end 1000", + expectedDescriptionV1 = "End offset (1001) is after ledger end (1000)", expectedCodeV2 = OUT_OF_RANGE, expectedDescriptionV2 = - "REQUESTED_OFFSET_OUT_OF_RANGE(12,0): End offset 1001 is after ledger end 1000", + "OFFSET_AFTER_LEDGER_END(12,0): End offset (1001) is after ledger end (1000)", ) } @@ -329,10 +329,10 @@ class TransactionServiceRequestValidatorTest ledgerEnd, ), expectedCodeV1 = OUT_OF_RANGE, - expectedDescriptionV1 = "Begin offset 1001 is after ledger end 1000", + expectedDescriptionV1 = "Begin offset (1001) is after ledger end (1000)", expectedCodeV2 = OUT_OF_RANGE, expectedDescriptionV2 = - "REQUESTED_OFFSET_OUT_OF_RANGE(12,0): Begin offset 1001 is after ledger end 1000", + "OFFSET_AFTER_LEDGER_END(12,0): Begin offset (1001) is after ledger end (1000)", ) } @@ -345,10 +345,10 @@ class TransactionServiceRequestValidatorTest ledgerEnd, ), expectedCodeV1 = OUT_OF_RANGE, - expectedDescriptionV1 = "End offset 1001 is after ledger end 1000", + expectedDescriptionV1 = "End offset (1001) is after ledger end (1000)", expectedCodeV2 = OUT_OF_RANGE, expectedDescriptionV2 = - "REQUESTED_OFFSET_OUT_OF_RANGE(12,0): End offset 1001 is after ledger end 1000", + "OFFSET_AFTER_LEDGER_END(12,0): End offset (1001) is after ledger end (1000)", ) } } 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 f81ec47619ef..46d6021d8611 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 @@ -3,17 +3,13 @@ package com.daml -import com.daml.error.utils.ErrorDetails -import com.daml.error.{ - ContextualizedErrorLogger, - DamlContextualizedErrorLogger, - ErrorCodesVersionSwitcher, -} -import com.daml.ledger.api.domain.LedgerId -import com.daml.lf.data.Ref -import com.daml.logging.{ContextualizedLogger, LoggingContext} -import com.daml.platform.server.api.validation.ErrorFactories -import com.daml.platform.server.api.validation.ErrorFactories._ +import error.utils.ErrorDetails +import error.{ContextualizedErrorLogger, DamlContextualizedErrorLogger, ErrorCodesVersionSwitcher} +import ledger.api.domain.LedgerId +import lf.data.Ref +import logging.{ContextualizedLogger, LoggingContext} +import platform.server.api.validation.ErrorFactories +import platform.server.api.validation.ErrorFactories._ import com.google.rpc._ import io.grpc.Status.Code import io.grpc.StatusRuntimeException @@ -22,11 +18,13 @@ import org.mockito.MockitoSugar import org.scalatest.matchers.should.Matchers import org.scalatest.prop.TableDrivenPropertyChecks import org.scalatest.wordspec.AnyWordSpec + import java.sql.{SQLNonTransientException, SQLTransientException} import java.time.Duration - +import scala.annotation.nowarn import scala.jdk.CollectionConverters._ +@nowarn("msg=deprecated") class ErrorFactoriesSpec extends AnyWordSpec with Matchers @@ -79,24 +77,6 @@ class ErrorFactoriesSpec ) } - "return malformedPackageId" in { - assertVersionedError( - _.malformedPackageId("message123")( - contextualizedErrorLogger = contextualizedErrorLogger - ) - )( - v1_code = Code.INVALID_ARGUMENT, - v1_message = "message123", - v1_details = Seq.empty, - v2_code = Code.INVALID_ARGUMENT, - v2_message = s"MALFORMED_PACKAGE_ID(8,$correlationId): message123", - v2_details = Seq[ErrorDetails.ErrorDetail]( - ErrorDetails.ErrorInfoDetail("MALFORMED_PACKAGE_ID"), - DefaultTraceIdRequestInfo, - ), - ) - } - "return packageNotFound" in { assertVersionedError(_.packageNotFound("packageId123"))( v1_code = Code.NOT_FOUND, @@ -112,7 +92,7 @@ class ErrorFactoriesSpec ) } - "return the internalError" in { + "return the a versioned service internal error" in { assertVersionedError(_.versionServiceInternalError("message123"))( v1_code = Code.INTERNAL, v1_message = "message123", @@ -121,7 +101,7 @@ class ErrorFactoriesSpec v2_message = s"An error occurred. Please contact the operator and inquire about the request trace-id", v2_details = Seq[ErrorDetails.ErrorDetail]( - ErrorDetails.ErrorInfoDetail("VERSION_SERVICE_INTERNAL_ERROR"), + ErrorDetails.ErrorInfoDetail("LEDGER_API_INTERNAL_ERROR"), DefaultTraceIdRequestInfo, ), ) @@ -225,15 +205,30 @@ class ErrorFactoriesSpec ) } - "return a offsetOutOfRange_was_invalidArgument error" in { - assertVersionedError(_.offsetOutOfRange_was_invalidArgument(None)("message123"))( + "return an offsetAfterLedgerEnd error" in { + val expectedMessage = s"Absolute offset (AABBCC) is after ledger end (E)" + assertVersionedError(_.offsetAfterLedgerEnd("Absolute", "AABBCC", "E"))( + v1_code = Code.OUT_OF_RANGE, + v1_message = expectedMessage, + v1_details = Seq.empty, + v2_code = Code.OUT_OF_RANGE, + v2_message = s"OFFSET_AFTER_LEDGER_END(12,$correlationId): $expectedMessage", + v2_details = Seq[ErrorDetails.ErrorDetail]( + ErrorDetails.ErrorInfoDetail("OFFSET_AFTER_LEDGER_END"), + DefaultTraceIdRequestInfo, + ), + ) + } + + "return a offsetOutOfRange error" in { + assertVersionedError(_.offsetOutOfRange(None)("message123"))( v1_code = Code.INVALID_ARGUMENT, v1_message = "Invalid argument: message123", v1_details = Seq.empty, - v2_code = Code.OUT_OF_RANGE, - v2_message = s"REQUESTED_OFFSET_OUT_OF_RANGE(12,$correlationId): message123", + v2_code = Code.FAILED_PRECONDITION, + v2_message = s"OFFSET_OUT_OF_RANGE(9,$correlationId): message123", v2_details = Seq[ErrorDetails.ErrorDetail]( - ErrorDetails.ErrorInfoDetail("REQUESTED_OFFSET_OUT_OF_RANGE"), + ErrorDetails.ErrorInfoDetail("OFFSET_OUT_OF_RANGE"), DefaultTraceIdRequestInfo, ), ) @@ -278,14 +273,16 @@ class ErrorFactoriesSpec (Some(false), Seq(definiteAnswers(false))), ) + val legacyErrorCode = Code.UNAVAILABLE + forEvery(testCases) { (definiteAnswer, expectedDetails) => - assertVersionedError(_.missingLedgerConfig(definiteAnswer))( - v1_code = Code.UNAVAILABLE, + assertVersionedError(_.missingLedgerConfig(legacyErrorCode)(definiteAnswer))( + v1_code = legacyErrorCode, v1_message = "The ledger configuration is not available.", v1_details = expectedDetails, v2_code = Code.NOT_FOUND, v2_message = - s"LEDGER_CONFIGURATION_NOT_FOUND(11,$correlationId): The ledger configuration is not available.", + s"LEDGER_CONFIGURATION_NOT_FOUND(11,$correlationId): The ledger configuration could not be retrieved.", v2_details = Seq[ErrorDetails.ErrorDetail]( ErrorDetails.ErrorInfoDetail("LEDGER_CONFIGURATION_NOT_FOUND"), DefaultTraceIdRequestInfo, @@ -295,8 +292,6 @@ class ErrorFactoriesSpec } "return an aborted error" in { - // TODO error codes: This error code is not specific enough. - // Break down into more specific errors. val testCases = Table( ("definite answer", "expected details"), (None, Seq.empty), @@ -392,8 +387,8 @@ class ErrorFactoriesSpec v1_code = Code.NOT_FOUND, v1_message = "my message", v1_details = Seq.empty, - v2_code = Code.OUT_OF_RANGE, - v2_message = s"PARTICIPANT_PRUNED_DATA_ACCESSED(12,$correlationId): my message", + v2_code = Code.FAILED_PRECONDITION, + v2_message = s"PARTICIPANT_PRUNED_DATA_ACCESSED(9,$correlationId): my message", v2_details = Seq[ErrorDetails.ErrorDetail]( ErrorDetails.ErrorInfoDetail("PARTICIPANT_PRUNED_DATA_ACCESSED"), DefaultTraceIdRequestInfo, @@ -416,34 +411,21 @@ class ErrorFactoriesSpec ) } - "return an offsetOutOfRange error" in { - assertVersionedError(_.offsetOutOfRange("my message"))( - v1_code = Code.OUT_OF_RANGE, - v1_message = "my message", - v1_details = Seq.empty, - v2_code = Code.OUT_OF_RANGE, - v2_message = s"REQUESTED_OFFSET_OUT_OF_RANGE(12,$correlationId): my message", - v2_details = Seq[ErrorDetails.ErrorDetail]( - ErrorDetails.ErrorInfoDetail("REQUESTED_OFFSET_OUT_OF_RANGE"), - DefaultTraceIdRequestInfo, - ), - ) - } - "return a serviceNotRunning error" in { val testCases = Table( ("definite answer", "expected details"), (None, Seq.empty), (Some(false), Seq(definiteAnswers(false))), ) + val serviceName = "Some API Service" forEvery(testCases) { (definiteAnswer, expectedDetails) => - assertVersionedError(_.serviceNotRunning(definiteAnswer))( + assertVersionedError(_.serviceNotRunning(serviceName)(definiteAnswer))( v1_code = Code.UNAVAILABLE, - v1_message = "Service has been shut down.", + v1_message = s"$serviceName has been shut down.", v1_details = expectedDetails, v2_code = Code.UNAVAILABLE, - v2_message = s"SERVICE_NOT_RUNNING(1,$correlationId): Service has been shut down.", + v2_message = s"SERVICE_NOT_RUNNING(1,$correlationId): $serviceName has been shut down.", v2_details = Seq[ErrorDetails.ErrorDetail]( ErrorDetails.ErrorInfoDetail("SERVICE_NOT_RUNNING"), DefaultTraceIdRequestInfo, @@ -453,21 +435,6 @@ class ErrorFactoriesSpec } } - "return a missingLedgerConfigUponRequest error" in { - assertVersionedError(_.missingLedgerConfigUponRequest)( - v1_code = Code.NOT_FOUND, - v1_message = "The ledger configuration is not available.", - v1_details = Seq.empty, - v2_code = Code.NOT_FOUND, - v2_message = - s"LEDGER_CONFIGURATION_NOT_FOUND(11,$correlationId): The ledger configuration is not available.", - v2_details = Seq[ErrorDetails.ErrorDetail]( - ErrorDetails.ErrorInfoDetail("LEDGER_CONFIGURATION_NOT_FOUND"), - DefaultTraceIdRequestInfo, - ), - ) - } - "return a missingField error" in { val testCases = Table( ("definite answer", "expected details"), diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala index a6551de607c0..88f847656ae4 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/infrastructure/deduplication/CommandDeduplicationBase.scala @@ -112,14 +112,14 @@ private[testtool] abstract class CommandDeduplicationBase( _ <- submitRequestAndAssertSyncFailure(ledger)( requestA, Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, ) // Re-submit the invalid command (should again fail with INVALID_ARGUMENT and not with ALREADY_EXISTS) _ <- submitRequestAndAssertSyncFailure(ledger)( requestA, Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, ) } yield {} }) @@ -369,7 +369,7 @@ private[testtool] abstract class CommandDeduplicationBase( submitRequestAndAssertSyncFailure(ledger)( request, Code.ALREADY_EXISTS, - LedgerApiErrors.CommandRejections.DuplicateCommand, + LedgerApiErrors.ConsistencyErrors.DuplicateCommand, ) private def submitRequestAndAssertSyncFailure(ledger: ParticipantTestContext)( @@ -401,7 +401,7 @@ private[testtool] abstract class CommandDeduplicationBase( ledger, _, expectedCode = Code.ALREADY_EXISTS, - selfServiceErrorCode = LedgerApiErrors.CommandRejections.DuplicateCommand, + selfServiceErrorCode = LedgerApiErrors.ConsistencyErrors.DuplicateCommand, exceptionMessageSubstring = None, checkDefiniteAnswerMetadata = true, ) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ActiveContractsServiceIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ActiveContractsServiceIT.scala index f7f974cc0da3..b1424f053d23 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ActiveContractsServiceIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ActiveContractsServiceIT.scala @@ -46,7 +46,7 @@ class ActiveContractsServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some("not found. Actual Ledger ID"), ) } diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ClosedWorldIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ClosedWorldIT.scala index a4dded68cde5..d7c88b7a2e6a 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ClosedWorldIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ClosedWorldIT.scala @@ -35,7 +35,7 @@ class ClosedWorldIT extends LedgerTestSuite { alpha, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandRejections.PartyNotKnownOnLedger, + LedgerApiErrors.WriteServiceRejections.PartyNotKnownOnLedger, Some(Pattern.compile("Part(y|ies) not known on ledger")), checkDefiniteAnswerMetadata = true, ) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala index 6e51e18096d7..a0b57eb988c2 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandServiceIT.scala @@ -160,7 +160,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.ALREADY_EXISTS, - LedgerApiErrors.CommandRejections.DuplicateCommand, + LedgerApiErrors.ConsistencyErrors.DuplicateCommand, None, checkDefiniteAnswerMetadata = true, ) @@ -183,7 +183,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.ALREADY_EXISTS, - LedgerApiErrors.CommandRejections.DuplicateCommand, + LedgerApiErrors.ConsistencyErrors.DuplicateCommand, None, checkDefiniteAnswerMetadata = true, ) @@ -206,7 +206,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.ALREADY_EXISTS, - LedgerApiErrors.CommandRejections.DuplicateCommand, + LedgerApiErrors.ConsistencyErrors.DuplicateCommand, None, checkDefiniteAnswerMetadata = true, ) @@ -229,7 +229,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.ALREADY_EXISTS, - LedgerApiErrors.CommandRejections.DuplicateCommand, + LedgerApiErrors.ConsistencyErrors.DuplicateCommand, None, checkDefiniteAnswerMetadata = true, ) @@ -253,7 +253,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), checkDefiniteAnswerMetadata = true, ) @@ -276,7 +276,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), checkDefiniteAnswerMetadata = true, ) @@ -299,7 +299,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), checkDefiniteAnswerMetadata = true, ) @@ -322,7 +322,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.PreprocessingErrors.PreprocessingFailed, + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, Some(Pattern.compile(s"Missing record (label|field)")), checkDefiniteAnswerMetadata = true, ) @@ -344,7 +344,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.GenericInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError, Some( Pattern.compile( "Interpretation error: Error: (User abort: Assertion failed.|Unhandled exception: [0-9a-zA-Z\\.:]*@[0-9a-f]*\\{ message = \"Assertion failed\" \\}\\.) [Dd]etails(: |=)Last location: \\[[^\\]]*\\], partial transaction: root node" @@ -503,7 +503,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, e1, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.PreprocessingErrors.PreprocessingFailed, + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, Some("Cannot represent"), checkDefiniteAnswerMetadata = true, ) @@ -511,7 +511,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, e2, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.PreprocessingErrors.PreprocessingFailed, + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, Some("Out-of-bounds (Numeric 10)"), checkDefiniteAnswerMetadata = true, ) @@ -519,7 +519,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, e3, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.PreprocessingErrors.PreprocessingFailed, + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, Some("Out-of-bounds (Numeric 10)"), checkDefiniteAnswerMetadata = true, ) @@ -574,7 +574,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.PreprocessingErrors.PreprocessingFailed, + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, Some("Expecting 1 field for record"), checkDefiniteAnswerMetadata = true, ) @@ -600,7 +600,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.PreprocessingErrors.PreprocessingFailed, + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, Some("mismatching type"), checkDefiniteAnswerMetadata = true, ) @@ -627,7 +627,7 @@ final class CommandServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.PreprocessingErrors.PreprocessingFailed, + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, Some( Pattern.compile( "(unknown|Couldn't find requested) choice " + missingChoice diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandSubmissionCompletionIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandSubmissionCompletionIT.scala index 467f257eda3d..cc75bb3dd780 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandSubmissionCompletionIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/CommandSubmissionCompletionIT.scala @@ -74,7 +74,7 @@ final class CommandSubmissionCompletionIT extends LedgerTestSuite { ledger, failure, Status.Code.OUT_OF_RANGE, - LedgerApiErrors.ReadErrors.RequestedOffsetOutOfRange, + LedgerApiErrors.RequestValidation.OffsetAfterLedgerEnd, Some("is after ledger end"), ) } @@ -112,7 +112,7 @@ final class CommandSubmissionCompletionIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.PreprocessingErrors.PreprocessingFailed, + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, Some( Pattern.compile( "(unknown|Couldn't find requested) choice " + badChoice @@ -138,7 +138,7 @@ final class CommandSubmissionCompletionIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), checkDefiniteAnswerMetadata = true, ) @@ -157,7 +157,7 @@ final class CommandSubmissionCompletionIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.MissingField, + LedgerApiErrors.RequestValidation.MissingField, Some("commands"), checkDefiniteAnswerMetadata = true, ) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ConfigManagementServiceIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ConfigManagementServiceIT.scala index d8be1992724c..4ae983a109ed 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ConfigManagementServiceIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ConfigManagementServiceIT.scala @@ -95,7 +95,7 @@ final class ConfigManagementServiceIT extends LedgerTestSuite { ledger, expiredMRTFailure, Status.Code.ABORTED, - LedgerApiErrors.WriteErrors.RequestTimeOut, + LedgerApiErrors.AdminServices.RequestTimeOut, exceptionMessageSubstring = None, ) } @@ -141,7 +141,7 @@ final class ConfigManagementServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.InvalidArgument, + LedgerApiErrors.RequestValidation.InvalidArgument, exceptionMessageSubstring = None, ) } @@ -191,7 +191,7 @@ final class ConfigManagementServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.InvalidArgument, + LedgerApiErrors.RequestValidation.InvalidArgument, Some("Mismatching configuration generation"), ) }.recover { case _ => @@ -200,7 +200,7 @@ final class ConfigManagementServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.ABORTED, - LedgerApiErrors.WriteErrors.ConfigurationEntryRejected, + LedgerApiErrors.AdminServices.ConfigurationEntryRejected, Some("Generation mismatch"), ) } match { diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractIdIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractIdIT.scala index 5b684c4b46b3..7f346d6e379d 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractIdIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractIdIT.scala @@ -61,7 +61,7 @@ final class ContractIdIT extends LedgerTestSuite { alpha, err, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.PreprocessingErrors.PreprocessingFailed, + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, Some(s"""Illegal Contract ID "$testedCid""""), checkDefiniteAnswerMetadata = true, ) @@ -101,8 +101,7 @@ final class ContractIdIT extends LedgerTestSuite { Try( assertSelfServiceErrorCode( statusRuntimeException = exception, - expectedErrorCode = - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + expectedErrorCode = LedgerApiErrors.ConsistencyErrors.ContractNotFound, ) ).isSuccess => Success(()) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractKeysIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractKeysIT.scala index 875243d197a0..957cdc4ec4d6 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractKeysIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ContractKeysIT.scala @@ -77,14 +77,14 @@ final class ContractKeysIT extends LedgerTestSuite { beta, fetchFailure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, Some("couldn't find key"), ) assertGrpcErrorRegex( beta, lookupByKeyFailure, Status.Code.ABORTED, - LedgerApiErrors.CommandRejections.InconsistentContractKey, + LedgerApiErrors.ConsistencyErrors.InconsistentContractKey, Some(Pattern.compile("Inconsistent|Contract key lookup with different results")), checkDefiniteAnswerMetadata = true, ) @@ -128,7 +128,7 @@ final class ContractKeysIT extends LedgerTestSuite { beta, fetchFailure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) @@ -136,14 +136,14 @@ final class ContractKeysIT extends LedgerTestSuite { beta, fetchByKeyFailure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, Some("couldn't find key"), ) assertGrpcErrorRegex( beta, lookupByKeyFailure, Status.Code.ABORTED, - LedgerApiErrors.CommandRejections.InconsistentContractKey, + LedgerApiErrors.ConsistencyErrors.InconsistentContractKey, Some(Pattern.compile("Inconsistent|Contract key lookup with different results")), checkDefiniteAnswerMetadata = true, ) @@ -218,7 +218,7 @@ final class ContractKeysIT extends LedgerTestSuite { alpha, duplicateKeyFailure, Status.Code.ABORTED, - LedgerApiErrors.CommandRejections.DuplicateContractKey, + LedgerApiErrors.ConsistencyErrors.DuplicateContractKey, Some(Pattern.compile("Inconsistent|contract key is not unique")), checkDefiniteAnswerMetadata = true, ) @@ -226,7 +226,7 @@ final class ContractKeysIT extends LedgerTestSuite { beta, bobLooksUpTextKeyFailure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, Some("requires authorizers"), checkDefiniteAnswerMetadata = true, ) @@ -234,7 +234,7 @@ final class ContractKeysIT extends LedgerTestSuite { beta, bobLooksUpBogusTextKeyFailure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, Some("requires authorizers"), checkDefiniteAnswerMetadata = true, ) @@ -242,7 +242,7 @@ final class ContractKeysIT extends LedgerTestSuite { alpha, aliceFailedFetch, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, Some("couldn't find key"), checkDefiniteAnswerMetadata = true, ) @@ -250,7 +250,7 @@ final class ContractKeysIT extends LedgerTestSuite { alpha, maintainerNotSignatoryFailed, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, Some("are not a subset of the signatories"), checkDefiniteAnswerMetadata = true, ) @@ -314,7 +314,7 @@ final class ContractKeysIT extends LedgerTestSuite { ledger, failedFetch, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, Some("couldn't find key"), checkDefiniteAnswerMetadata = true, ) @@ -393,7 +393,7 @@ final class ContractKeysIT extends LedgerTestSuite { ledger, failureBeforeCreation, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, Some("dependency error: couldn't find key"), checkDefiniteAnswerMetadata = true, ) @@ -401,7 +401,7 @@ final class ContractKeysIT extends LedgerTestSuite { ledger, failureAfterConsuming, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, Some("dependency error: couldn't find key"), checkDefiniteAnswerMetadata = true, ) @@ -439,7 +439,7 @@ final class ContractKeysIT extends LedgerTestSuite { ledger2, failedLookup, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.GenericInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError, Some("not visible"), checkDefiniteAnswerMetadata = true, ) @@ -447,7 +447,7 @@ final class ContractKeysIT extends LedgerTestSuite { ledger2, failedFetch, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.GenericInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError, Some("not visible"), checkDefiniteAnswerMetadata = true, ) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeeplyNestedValueIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeeplyNestedValueIT.scala index 924878fa75c1..6d5c22e289e3 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeeplyNestedValueIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/DeeplyNestedValueIT.scala @@ -84,26 +84,30 @@ final class DeeplyNestedValueIT extends LedgerTestSuite { } }) - test("create command", LedgerApiErrors.PreprocessingErrors.PreprocessingFailed) { - implicit ec => (alpha, party) => - waitForTransactionId(alpha, party, Contract(party, nContract, toNat(nContract)).create) + test( + "create command", + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, + ) { implicit ec => (alpha, party) => + waitForTransactionId(alpha, party, Contract(party, nContract, toNat(nContract)).create) } - test("exercise command", LedgerApiErrors.PreprocessingErrors.PreprocessingFailed) { - implicit ec => (alpha, party) => - for { - handler <- alpha.create(party, Handler(party)) - result <- waitForTransactionId( - alpha, - party, - handler.exerciseDestruct(party, toNat(nChoiceArgument)), - ) - } yield result + test( + "exercise command", + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, + ) { implicit ec => (alpha, party) => + for { + handler <- alpha.create(party, Handler(party)) + result <- waitForTransactionId( + alpha, + party, + handler.exerciseDestruct(party, toNat(nChoiceArgument)), + ) + } yield result } test( "create argument in CreateAndExercise command", - LedgerApiErrors.PreprocessingErrors.PreprocessingFailed, + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, ) { implicit ec => (alpha, party) => waitForTransactionId( alpha, @@ -115,7 +119,7 @@ final class DeeplyNestedValueIT extends LedgerTestSuite { test( "choice argument in CreateAndExercise command", - LedgerApiErrors.PreprocessingErrors.PreprocessingFailed, + LedgerApiErrors.CommandExecution.Preprocessing.PreprocessingFailed, ) { implicit ec => (alpha, party) => waitForTransactionId( alpha, @@ -126,7 +130,7 @@ final class DeeplyNestedValueIT extends LedgerTestSuite { test( "exercise argument", - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError, ) { implicit ec => (alpha, party) => for { handler <- alpha.create(party, Handler(party)) @@ -139,47 +143,55 @@ final class DeeplyNestedValueIT extends LedgerTestSuite { } yield result } - test("exercise output", LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError) { - implicit ec => (alpha, party) => - for { - handler <- alpha.create(party, Handler(party)) - result <- - waitForTransactionId(alpha, party, handler.exerciseConstruct(party, n)) - } yield result + test( + "exercise output", + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError, + ) { implicit ec => (alpha, party) => + for { + handler <- alpha.create(party, Handler(party)) + result <- + waitForTransactionId(alpha, party, handler.exerciseConstruct(party, n)) + } yield result } - test("create argument", LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError) { - implicit ec => (alpha, party) => - for { - handler <- alpha.create(party, Handler(party)) - result <- waitForTransactionId(alpha, party, handler.exerciseCreate(party, nContract)) - } yield result + test( + "create argument", + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError, + ) { implicit ec => (alpha, party) => + for { + handler <- alpha.create(party, Handler(party)) + result <- waitForTransactionId(alpha, party, handler.exerciseCreate(party, nContract)) + } yield result } - test("contract key", LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError) { - implicit ec => (alpha, party) => - for { - handler <- alpha.create(party, Handler(party)) - result <- waitForTransactionId(alpha, party, handler.exerciseCreateKey(party, nKey)) - } yield result + test( + "contract key", + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError, + ) { implicit ec => (alpha, party) => + for { + handler <- alpha.create(party, Handler(party)) + result <- waitForTransactionId(alpha, party, handler.exerciseCreateKey(party, nKey)) + } yield result } if (accepted) { // Because we cannot create contracts with nesting > 100, // it does not make sense to test fetch of those kinds of contracts. - test("fetch by key", LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError) { - implicit ec => (alpha, party) => - for { - handler <- alpha.create(party, Handler(party)) - _ <- alpha.exercise(party, handler.exerciseCreateKey(_, nKey)) - result <- waitForTransactionId(alpha, party, handler.exerciseFetchByKey(party, nKey)) - } yield result + test( + "fetch by key", + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError, + ) { implicit ec => (alpha, party) => + for { + handler <- alpha.create(party, Handler(party)) + _ <- alpha.exercise(party, handler.exerciseCreateKey(_, nKey)) + result <- waitForTransactionId(alpha, party, handler.exerciseFetchByKey(party, nKey)) + } yield result } } test( "failing lookup by key", - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError, ) { implicit ec => (alpha, party) => for { handler <- alpha.create(party, Handler(party)) @@ -192,7 +204,7 @@ final class DeeplyNestedValueIT extends LedgerTestSuite { // it does not make sens to test successful lookup for those keys. test( "successful lookup by key", - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError, ) { implicit ec => (alpha, party) => for { handler <- alpha.create(party, Handler(party)) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ExceptionsIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ExceptionsIT.scala index b004739560c2..631cc8eca286 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ExceptionsIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ExceptionsIT.scala @@ -26,7 +26,7 @@ final class ExceptionsIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.GenericInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError, Some("Unhandled exception"), checkDefiniteAnswerMetadata = true, ) @@ -79,7 +79,7 @@ final class ExceptionsIT extends LedgerTestSuite { ledger, failure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) @@ -104,7 +104,7 @@ final class ExceptionsIT extends LedgerTestSuite { ledger, failure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) @@ -129,7 +129,7 @@ final class ExceptionsIT extends LedgerTestSuite { ledger, failure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) @@ -186,7 +186,7 @@ final class ExceptionsIT extends LedgerTestSuite { ledger, failure, Status.Code.ABORTED, - LedgerApiErrors.CommandRejections.DuplicateContractKey, + LedgerApiErrors.ConsistencyErrors.DuplicateContractKey, Some("DuplicateKey"), checkDefiniteAnswerMetadata = true, ) @@ -206,7 +206,7 @@ final class ExceptionsIT extends LedgerTestSuite { ledger, failure, Status.Code.ABORTED, - LedgerApiErrors.CommandRejections.DuplicateContractKey, + LedgerApiErrors.ConsistencyErrors.DuplicateContractKey, Some("DuplicateKey"), checkDefiniteAnswerMetadata = true, ) @@ -231,7 +231,7 @@ final class ExceptionsIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, Some("couldn't find key"), checkDefiniteAnswerMetadata = true, ) @@ -251,7 +251,7 @@ final class ExceptionsIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, Some("couldn't find key"), checkDefiniteAnswerMetadata = true, ) @@ -296,7 +296,7 @@ final class ExceptionsIT extends LedgerTestSuite { aLedger, fetchFailure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) @@ -325,7 +325,7 @@ final class ExceptionsIT extends LedgerTestSuite { bLedger, fetchFailure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) @@ -336,7 +336,7 @@ final class ExceptionsIT extends LedgerTestSuite { bLedger, fetchFailure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/LedgerConfigurationServiceIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/LedgerConfigurationServiceIT.scala index f9802b807648..c922c1b3668a 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/LedgerConfigurationServiceIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/LedgerConfigurationServiceIT.scala @@ -38,7 +38,7 @@ class LedgerConfigurationServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), ) } @@ -85,8 +85,8 @@ class LedgerConfigurationServiceIT extends LedgerTestSuite { else Status.Code.INVALID_ARGUMENT val expectedError = if (ledger.features.selfServiceErrorCodes) - LedgerApiErrors.CommandValidation.InvalidDeduplicationPeriodField - else LedgerApiErrors.CommandValidation.InvalidField + LedgerApiErrors.RequestValidation.InvalidDeduplicationPeriodField + else LedgerApiErrors.RequestValidation.InvalidField assertGrpcErrorRegex( ledger, failure, diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/MultiPartySubmissionIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/MultiPartySubmissionIT.scala index b02ed38fa095..d2e1f80fca78 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/MultiPartySubmissionIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/MultiPartySubmissionIT.scala @@ -76,7 +76,7 @@ final class MultiPartySubmissionIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, None, checkDefiniteAnswerMetadata = true, ) @@ -126,7 +126,7 @@ final class MultiPartySubmissionIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, None, checkDefiniteAnswerMetadata = true, ) @@ -180,7 +180,7 @@ final class MultiPartySubmissionIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, Some(Pattern.compile("of the fetched contract to be an authorizer, but authorizers were")), checkDefiniteAnswerMetadata = true, ) @@ -213,7 +213,7 @@ final class MultiPartySubmissionIT extends LedgerTestSuite { ledger, failure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some(Pattern.compile("Contract could not be found")), checkDefiniteAnswerMetadata = true, ) @@ -267,7 +267,7 @@ final class MultiPartySubmissionIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, Some(Pattern.compile("of the fetched contract to be an authorizer, but authorizers were")), checkDefiniteAnswerMetadata = true, ) @@ -300,7 +300,7 @@ final class MultiPartySubmissionIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractKeyNotFound, + LedgerApiErrors.CommandExecution.Interpreter.LookupErrors.ContractKeyNotFound, Some(Pattern.compile("dependency error: couldn't find key")), checkDefiniteAnswerMetadata = true, ) @@ -356,7 +356,7 @@ final class MultiPartySubmissionIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, Some(Pattern.compile("requires authorizers (.*) for lookup by key, but it only has")), checkDefiniteAnswerMetadata = true, ) @@ -390,7 +390,7 @@ final class MultiPartySubmissionIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.GenericInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError, Some( Pattern.compile( "Interpretation error: Error: (User abort: Assertion failed.|Unhandled exception: [0-9a-zA-Z\\.:]*@[0-9a-f]*\\{ message = \"LookupOtherByKey value matches\" \\}\\.) [Dd]etails(: |=)Last location: \\[[^\\]]*\\], partial transaction: root node" diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/PackageServiceIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/PackageServiceIT.scala index 9c7be53d6635..414395ac3eed 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/PackageServiceIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/PackageServiceIT.scala @@ -59,7 +59,7 @@ final class PackageServiceIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.PackageNotFound, + LedgerApiErrors.RequestValidation.NotFound.Package, None, ) } diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ParticipantPruningIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ParticipantPruningIT.scala index 3d46f4dd3f11..d15edf8ea201 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ParticipantPruningIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/ParticipantPruningIT.scala @@ -42,7 +42,7 @@ class ParticipantPruningIT extends LedgerTestSuite { participant, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.InvalidArgument, + LedgerApiErrors.RequestValidation.InvalidArgument, Some("prune_up_to not specified"), ) } @@ -62,7 +62,7 @@ class ParticipantPruningIT extends LedgerTestSuite { participant, cannotPruneNonHexOffset, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.NonHexOffset, + LedgerApiErrors.RequestValidation.NonHexOffset, Some("prune_up_to needs to be a hexadecimal string and not"), ) } @@ -85,7 +85,7 @@ class ParticipantPruningIT extends LedgerTestSuite { participant, cannotPruneOffsetBeyondEnd, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.ReadErrors.RequestedOffsetOutOfRange, + LedgerApiErrors.RequestValidation.OffsetOutOfRange, Some("prune_up_to needs to be before ledger end"), ) } @@ -129,7 +129,7 @@ class ParticipantPruningIT extends LedgerTestSuite { participant, cannotReadAnymore, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.ParticipantPrunedDataAccessed, + LedgerApiErrors.RequestValidation.ParticipantPrunedDataAccessed, Some( Pattern.compile( s"(Transactions request from [0-9a-fA-F]* to [0-9a-fA-F]* precedes pruned offset ${offsetToPruneUpTo.getAbsolute})|(Request from [0-9a-fA-F]* precedes pruned offset ${offsetToPruneUpTo.getAbsolute})" @@ -177,7 +177,7 @@ class ParticipantPruningIT extends LedgerTestSuite { participant, cannotReadAnymore, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.ParticipantPrunedDataAccessed, + LedgerApiErrors.RequestValidation.ParticipantPrunedDataAccessed, Some( Pattern.compile( s"(Transactions request from [0-9a-fA-F]* to [0-9a-fA-F]* precedes pruned offset ${offsetToPruneUpTo.getAbsolute})|(Request from [0-9a-fA-F]* precedes pruned offset ${offsetToPruneUpTo.getAbsolute})" @@ -232,7 +232,7 @@ class ParticipantPruningIT extends LedgerTestSuite { participant, cannotReadAnymore, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.ParticipantPrunedDataAccessed, + LedgerApiErrors.RequestValidation.ParticipantPrunedDataAccessed, Some( Pattern.compile( s"Command completions? request from [0-9a-fA-F]* to [0-9a-fA-F]* overlaps with pruned offset ${offsetToPruneUpTo.getAbsolute}" @@ -304,7 +304,7 @@ class ParticipantPruningIT extends LedgerTestSuite { participant, _, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) ) @@ -353,7 +353,7 @@ class ParticipantPruningIT extends LedgerTestSuite { participant, _, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) ) @@ -398,7 +398,7 @@ class ParticipantPruningIT extends LedgerTestSuite { participant, _, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) ) @@ -443,7 +443,7 @@ class ParticipantPruningIT extends LedgerTestSuite { participant, _, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) ) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/PartyManagementServiceIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/PartyManagementServiceIT.scala index ac24976eeadc..8ca6f9b150eb 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/PartyManagementServiceIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/PartyManagementServiceIT.scala @@ -111,7 +111,7 @@ final class PartyManagementServiceIT extends LedgerTestSuite { ledger, error, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.InvalidArgument, + LedgerApiErrors.RequestValidation.InvalidArgument, Some("Party is too long"), ) } @@ -135,7 +135,7 @@ final class PartyManagementServiceIT extends LedgerTestSuite { ledger, error, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.InvalidArgument, + LedgerApiErrors.RequestValidation.InvalidArgument, Some("non expected character"), ) } diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/SemanticTests.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/SemanticTests.scala index ce32fe1f9592..410b6a3ff404 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/SemanticTests.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/SemanticTests.scala @@ -63,7 +63,7 @@ final class SemanticTests extends LedgerTestSuite { alpha, failure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) @@ -131,7 +131,7 @@ final class SemanticTests extends LedgerTestSuite { alpha, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.ContractNotActive, + LedgerApiErrors.CommandExecution.Interpreter.ContractNotActive, Some("Update failed due to fetch of an inactive contract"), checkDefiniteAnswerMetadata = true, ) @@ -156,7 +156,7 @@ final class SemanticTests extends LedgerTestSuite { beta, failure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) @@ -251,7 +251,7 @@ final class SemanticTests extends LedgerTestSuite { alpha, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, Some("requires authorizers"), checkDefiniteAnswerMetadata = true, ) @@ -275,7 +275,7 @@ final class SemanticTests extends LedgerTestSuite { beta, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, Some("requires authorizers"), checkDefiniteAnswerMetadata = true, ) @@ -343,7 +343,7 @@ final class SemanticTests extends LedgerTestSuite { beta, iouFetchFailure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) @@ -351,7 +351,7 @@ final class SemanticTests extends LedgerTestSuite { alpha, paintOfferFetchFailure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) @@ -359,7 +359,7 @@ final class SemanticTests extends LedgerTestSuite { alpha, paintAgreeFetchFailure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) @@ -367,7 +367,7 @@ final class SemanticTests extends LedgerTestSuite { alpha, secondIouFetchFailure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, Some("requires one of the stakeholders"), checkDefiniteAnswerMetadata = true, ) @@ -435,7 +435,7 @@ final class SemanticTests extends LedgerTestSuite { beta, failure, Status.Code.ABORTED, - LedgerApiErrors.InterpreterErrors.LookupErrors.ContractNotFound, + LedgerApiErrors.ConsistencyErrors.ContractNotFound, Some("Contract could not be found"), checkDefiniteAnswerMetadata = true, ) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceAuthorizationIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceAuthorizationIT.scala index 4606656802cb..4c82710d2bb1 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceAuthorizationIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceAuthorizationIT.scala @@ -98,7 +98,7 @@ class TransactionServiceAuthorizationIT extends LedgerTestSuite { beta, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.AuthorizationError, + LedgerApiErrors.CommandExecution.Interpreter.AuthorizationError, Some("requires authorizers"), checkDefiniteAnswerMetadata = true, ) @@ -138,7 +138,7 @@ class TransactionServiceAuthorizationIT extends LedgerTestSuite { beta, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.GenericInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError, Some("Assertion failed"), checkDefiniteAnswerMetadata = true, ) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceExerciseIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceExerciseIT.scala index ea6155e24db8..65650f2d24e8 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceExerciseIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceExerciseIT.scala @@ -133,7 +133,7 @@ class TransactionServiceExerciseIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.GenericInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.GenericInterpretationError, Some("Assertion failed"), checkDefiniteAnswerMetadata = true, ) diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceQueryIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceQueryIT.scala index 20faba16c6a5..862e6e803ddf 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceQueryIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceQueryIT.scala @@ -44,7 +44,7 @@ class TransactionServiceQueryIT extends LedgerTestSuite { beta, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) } @@ -64,7 +64,7 @@ class TransactionServiceQueryIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) } @@ -100,7 +100,7 @@ class TransactionServiceQueryIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) } @@ -120,7 +120,7 @@ class TransactionServiceQueryIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) } @@ -158,7 +158,7 @@ class TransactionServiceQueryIT extends LedgerTestSuite { beta, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) } @@ -178,7 +178,7 @@ class TransactionServiceQueryIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) } @@ -216,7 +216,7 @@ class TransactionServiceQueryIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) } @@ -236,7 +236,7 @@ class TransactionServiceQueryIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.ReadErrors.TransactionNotFound, + LedgerApiErrors.RequestValidation.NotFound.Transaction, Some("Transaction not found, or not visible."), ) } diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceStreamsIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceStreamsIT.scala index dda750c7b0c2..ab4fd5564638 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceStreamsIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceStreamsIT.scala @@ -84,7 +84,7 @@ class TransactionServiceStreamsIT extends LedgerTestSuite { ledger, failure, Status.Code.OUT_OF_RANGE, - LedgerApiErrors.ReadErrors.RequestedOffsetOutOfRange, + LedgerApiErrors.RequestValidation.OffsetAfterLedgerEnd, Some("is after ledger end"), ) } @@ -106,7 +106,7 @@ class TransactionServiceStreamsIT extends LedgerTestSuite { ledger, failure, Status.Code.OUT_OF_RANGE, - LedgerApiErrors.ReadErrors.RequestedOffsetOutOfRange, + LedgerApiErrors.RequestValidation.OffsetAfterLedgerEnd, Some("is after ledger end"), ) } diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceValidationIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceValidationIT.scala index 400bf2571d2d..54a3250cf792 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceValidationIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/TransactionServiceValidationIT.scala @@ -29,7 +29,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.InvalidArgument, + LedgerApiErrors.RequestValidation.InvalidArgument, Some("filtersByParty cannot be empty"), ) } @@ -54,7 +54,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.ReadErrors.RequestedOffsetOutOfRange, + LedgerApiErrors.RequestValidation.OffsetOutOfRange, Some("is before Begin offset"), ) } @@ -78,7 +78,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), ) } @@ -102,7 +102,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), ) } @@ -126,7 +126,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), ) } @@ -150,7 +150,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), ) } @@ -174,7 +174,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), ) } @@ -198,7 +198,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), ) } @@ -219,7 +219,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.NOT_FOUND, - LedgerApiErrors.CommandValidation.LedgerIdMismatch, + LedgerApiErrors.RequestValidation.LedgerIdMismatch, Some(s"Ledger ID '$invalidLedgerId' not found."), ) } @@ -239,7 +239,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.MissingField, + LedgerApiErrors.RequestValidation.MissingField, Some("requesting_parties"), ) } @@ -259,7 +259,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.MissingField, + LedgerApiErrors.RequestValidation.MissingField, Some("requesting_parties"), ) } @@ -279,7 +279,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.InvalidField, + LedgerApiErrors.RequestValidation.InvalidField, Some("Invalid field event_id"), ) } @@ -299,7 +299,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.MissingField, + LedgerApiErrors.RequestValidation.MissingField, Some("requesting_parties"), ) } @@ -319,7 +319,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.InvalidField, + LedgerApiErrors.RequestValidation.InvalidField, Some("Invalid field event_id"), ) } @@ -339,7 +339,7 @@ class TransactionServiceValidationIT extends LedgerTestSuite { ledger, failure, Status.Code.INVALID_ARGUMENT, - LedgerApiErrors.CommandValidation.MissingField, + LedgerApiErrors.RequestValidation.MissingField, Some("requesting_parties"), ) } diff --git a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/WronglyTypedContractIdIT.scala b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/WronglyTypedContractIdIT.scala index 911fb1b32176..43895a458c5d 100644 --- a/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/WronglyTypedContractIdIT.scala +++ b/ledger/ledger-api-test-tool/src/main/scala/com/daml/ledger/api/testtool/suites/WronglyTypedContractIdIT.scala @@ -27,7 +27,7 @@ final class WronglyTypedContractIdIT extends LedgerTestSuite { ledger, exerciseFailure, Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError, Some("wrongly typed contract id"), checkDefiniteAnswerMetadata = true, ) @@ -50,7 +50,7 @@ final class WronglyTypedContractIdIT extends LedgerTestSuite { ledger, fetchFailure, Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError, Some("wrongly typed contract id"), checkDefiniteAnswerMetadata = true, ) @@ -79,7 +79,7 @@ final class WronglyTypedContractIdIT extends LedgerTestSuite { ledger, failure, Code.INVALID_ARGUMENT, - LedgerApiErrors.InterpreterErrors.InvalidArgumentInterpretationError, + LedgerApiErrors.CommandExecution.Interpreter.InvalidArgumentInterpretationError, Some("wrongly typed contract id"), checkDefiniteAnswerMetadata = true, ) diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiCommandService.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiCommandService.scala index b5924de06995..32db49bf1f7a 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiCommandService.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiCommandService.scala @@ -163,7 +163,7 @@ private[apiserver] final class ApiCommandService private[services] ( ): Future[Either[TrackedCompletionFailure, CompletionSuccess]] = Future .failed( - errorFactories.serviceNotRunning(definiteAnswer = Some(false))( + errorFactories.serviceNotRunning("Command Service")(definiteAnswer = Some(false))( new DamlContextualizedErrorLogger( logger, loggingContext, diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiLedgerIdentityService.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiLedgerIdentityService.scala index 120a7b71b619..1448ff598433 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiLedgerIdentityService.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiLedgerIdentityService.scala @@ -44,7 +44,7 @@ private[apiserver] final class ApiLedgerIdentityService private ( ): Future[GetLedgerIdentityResponse] = { logger.info(s"Received request for ledger identity: $request") if (closed) - Future.failed(errorFactories.serviceNotRunning(None)) + Future.failed(errorFactories.serviceNotRunning("Ledger Identity Service")(None)) else getLedgerId() .map(ledgerId => GetLedgerIdentityResponse(ledgerId.unwrap)) diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiPackageService.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiPackageService.scala index 3dbff4a4886b..e35ac7ff51eb 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiPackageService.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiPackageService.scala @@ -96,9 +96,10 @@ private[apiserver] final class ApiPackageService private ( Future.failed[T]( ValidationLogger.logFailure( request, - errorFactories.malformedPackageId(errorMessage)( - createContextualizedErrorLogger - ), + errorFactories + .invalidArgument(Some(true))(s"Invalid package id: $errorMessage")( + createContextualizedErrorLogger + ), ) ), packageId => block(packageId), diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiSubmissionService.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiSubmissionService.scala index 929b1b141247..4d8ff2c3784c 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiSubmissionService.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/ApiSubmissionService.scala @@ -36,10 +36,11 @@ import com.daml.platform.server.api.validation.ErrorFactories import com.daml.platform.services.time.TimeProviderType import com.daml.telemetry.TelemetryContext import com.daml.timer.Delayed -import io.grpc.StatusRuntimeException +import io.grpc.{Status, StatusRuntimeException} import java.time.{Duration, Instant} import java.util.UUID +import scala.annotation.nowarn import scala.compat.java8.FutureConverters.CompletionStageOps import scala.concurrent.{ExecutionContext, Future} import scala.util.control.NonFatal @@ -146,7 +147,9 @@ private[apiserver] final class ApiSubmissionService private[services] ( } case None => Future.failed( - errorFactories.missingLedgerConfig(definiteAnswer = Some(false)) + errorFactories.missingLedgerConfig(Status.Code.UNAVAILABLE)(definiteAnswer = + Some(false) + ) ) } evaluatedCommand.andThen(logger.logErrorsOnCall[Unit]) @@ -324,6 +327,7 @@ private[apiserver] final class ApiSubmissionService private[services] ( /** This method encodes logic related to legacy error codes (V1). * Cf. self-service error codes (V2) in //ledger/error */ + @nowarn("msg=deprecated") private def toStatusExceptionV1( errorCause: ErrorCause )(implicit contextualizedErrorLogger: ContextualizedErrorLogger): StatusRuntimeException = { diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiConfigManagementService.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiConfigManagementService.scala index fa69da6a5e8a..7e832a6ec892 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiConfigManagementService.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiConfigManagementService.scala @@ -28,7 +28,7 @@ import com.daml.platform.apiserver.services.logging import com.daml.platform.server.api.ValidationLogger import com.daml.platform.server.api.validation.{ErrorFactories, FieldValidations} import com.daml.telemetry.{DefaultTelemetry, TelemetryContext} -import io.grpc.{ServerServiceDefinition, StatusRuntimeException} +import io.grpc.{ServerServiceDefinition, Status, StatusRuntimeException} import scala.compat.java8.FutureConverters._ import scala.concurrent.duration.{Duration, FiniteDuration} @@ -66,9 +66,8 @@ private[apiserver] final class ApiConfigManagementService private ( case Some((_, configuration)) => Future.successful(configurationToResponse(configuration)) case None => - // TODO error codes: Duplicate of missingLedgerConfig Future.failed( - missingLedgerConfigUponRequest( + missingLedgerConfig(Status.Code.NOT_FOUND)(Some(true))( new DamlContextualizedErrorLogger(logger, loggingContext, None) ) ) @@ -117,7 +116,7 @@ private[apiserver] final class ApiConfigManagementService private ( logger.warn( "Could not get the current time model. The index does not yet have any ledger configuration." ) - Future.failed(missingLedgerConfig(None)) + Future.failed(missingLedgerConfig(Status.Code.UNAVAILABLE)(None)) } (ledgerEndBeforeRequest, currentConfig) = configuration diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiParticipantPruningService.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiParticipantPruningService.scala index 83980f71a2c0..0e450acf9b6f 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiParticipantPruningService.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/ApiParticipantPruningService.scala @@ -174,7 +174,9 @@ final class ApiParticipantPruningService private ( if (pruneUpToString < ledgerEnd.value) Future.successful(()) else Future.failed( - offsetOutOfRange_was_invalidArgument(None)( + // TODO error codes: Relax the constraint (pruneUpToString <= ledgerEnd.value) + // and use offsetAfterLedgerEnd + offsetOutOfRange(None)( s"prune_up_to needs to be before ledger end ${ledgerEnd.value}" ) ) diff --git a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/SynchronousResponse.scala b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/SynchronousResponse.scala index 3380cc2ffa34..1114aa4c024e 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/SynchronousResponse.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/apiserver/services/admin/SynchronousResponse.scala @@ -59,7 +59,7 @@ class SynchronousResponse[Input, Entry, AcceptedEntry]( Future.failed( errorFactories .isTimeoutUnknown_wasAborted("Request timed out", definiteAnswer = Some(false))( - new DamlContextualizedErrorLogger(logger, loggingContext, None) + new DamlContextualizedErrorLogger(logger, loggingContext, Some(submissionId)) ) ) } diff --git a/ledger/participant-integration-api/src/main/scala/platform/index/LedgerBackedIndexService.scala b/ledger/participant-integration-api/src/main/scala/platform/index/LedgerBackedIndexService.scala index 2edb3a806dec..7a378f774e98 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/index/LedgerBackedIndexService.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/index/LedgerBackedIndexService.scala @@ -144,7 +144,7 @@ private[platform] final class LedgerBackedIndexService( Source.empty case Some(end) if begin > end => Source.failed( - errorFactories.offsetOutOfRange_was_invalidArgument(None)( + errorFactories.offsetOutOfRange(None)( s"End offset ${end.toApiString} is before Begin offset ${begin.toApiString}." )(new DamlContextualizedErrorLogger(logger, loggingContext, None)) ) diff --git a/ledger/participant-integration-api/src/main/scala/platform/store/appendonlydao/JdbcLedgerDao.scala b/ledger/participant-integration-api/src/main/scala/platform/store/appendonlydao/JdbcLedgerDao.scala index 39c798dfa6c4..2896131c5ad0 100644 --- a/ledger/participant-integration-api/src/main/scala/platform/store/appendonlydao/JdbcLedgerDao.scala +++ b/ledger/participant-integration-api/src/main/scala/platform/store/appendonlydao/JdbcLedgerDao.scala @@ -596,7 +596,7 @@ private class JdbcLedgerDao( conn, ) ) { - throw errorFactories.offsetOutOfRange_was_invalidArgument(None)( + throw errorFactories.offsetOutOfRange(None)( "Pruning offset for all divulged contracts needs to be after the migration offset" )(new DamlContextualizedErrorLogger(logger, loggingContext, None)) } diff --git a/ledger/participant-integration-api/src/test/suite/scala/platform/store/ConversionsSpec.scala b/ledger/participant-integration-api/src/test/suite/scala/platform/store/ConversionsSpec.scala index 0f0c85059609..82a34f733328 100644 --- a/ledger/participant-integration-api/src/test/suite/scala/platform/store/ConversionsSpec.scala +++ b/ledger/participant-integration-api/src/test/suite/scala/platform/store/ConversionsSpec.scala @@ -48,7 +48,7 @@ class ConversionsSpec extends AsyncWordSpec with Matchers { v1expectedCode = Status.Code.ABORTED.value(), v1expectedMessage = "Inconsistent: Could not lookup contracts: [cId_1, cId_2]", v2expectedCode = Status.Code.NOT_FOUND.value(), - v2expectedMessage = "CONTRACTS_NOT_FOUND(11,0): Unknown contracts: [cId_1, cId_2]", + v2expectedMessage = "CONTRACT_NOT_FOUND(11,0): Unknown contracts: [cId_1, cId_2]", ) } diff --git a/ledger/participant-state/kvutils/src/main/scala/com/daml/ledger/participant/state/kvutils/errors/KVErrors.scala b/ledger/participant-state/kvutils/src/main/scala/com/daml/ledger/participant/state/kvutils/errors/KVErrors.scala index 34f6135048a1..1bdc5ca53245 100644 --- a/ledger/participant-state/kvutils/src/main/scala/com/daml/ledger/participant/state/kvutils/errors/KVErrors.scala +++ b/ledger/participant-state/kvutils/src/main/scala/com/daml/ledger/participant/state/kvutils/errors/KVErrors.scala @@ -3,6 +3,8 @@ package com.daml.ledger.participant.state.kvutils.errors +import com.daml.error.definitions.ErrorGroups + import java.time.Instant import com.daml.error.{ ContextualizedErrorLogger, @@ -12,14 +14,13 @@ import com.daml.error.{ Explanation, Resolution, } -import com.daml.error.definitions.ErrorGroups.ParticipantErrorGroup.TransactionErrorGroup.LedgerApiErrorGroup import com.daml.ledger.participant.state.kvutils.committer.transaction.Rejection.InternallyInconsistentTransaction @Explanation( "Errors that are specific to ledgers based on the KV architecture. " + "Note that this section will soon cover all ledgers due to an ongoing error consolidation effort." ) -object KVErrors extends LedgerApiErrorGroup { +object KVErrors extends ErrorGroup()(ErrorGroups.rootErrorClass) { @Explanation("Errors that relate to the Daml concepts of time.") object Time extends ErrorGroup() { diff --git a/ledger/participant-state/kvutils/src/main/scala/com/daml/ledger/participant/state/kvutils/updates/TransactionRejections.scala b/ledger/participant-state/kvutils/src/main/scala/com/daml/ledger/participant/state/kvutils/updates/TransactionRejections.scala index a540622f37a8..5cb1fe0d605b 100644 --- a/ledger/participant-state/kvutils/src/main/scala/com/daml/ledger/participant/state/kvutils/updates/TransactionRejections.scala +++ b/ledger/participant-state/kvutils/src/main/scala/com/daml/ledger/participant/state/kvutils/updates/TransactionRejections.scala @@ -448,7 +448,7 @@ private[kvutils] object TransactionRejections { loggingContext: ContextualizedErrorLogger ): Status = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.DuplicateContractKey + LedgerApiErrors.ConsistencyErrors.DuplicateContractKey .LedgerReject(ExternallyInconsistentTransaction.DuplicateKeys.description) .asGrpcStatusFromContext ) @@ -456,7 +456,7 @@ private[kvutils] object TransactionRejections { def externallyInconsistentKeysStatus( )(implicit loggingContext: ContextualizedErrorLogger): Status = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.InconsistentContractKey + LedgerApiErrors.ConsistencyErrors.InconsistentContractKey .Reject(ExternallyInconsistentTransaction.InconsistentKeys.description) .asGrpcStatusFromContext ) @@ -464,7 +464,7 @@ private[kvutils] object TransactionRejections { def externallyInconsistentContractsStatus( )(implicit loggingContext: ContextualizedErrorLogger): Status = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.InconsistentContracts + LedgerApiErrors.ConsistencyErrors.InconsistentContracts .Reject(ExternallyInconsistentTransaction.InconsistentContracts.description) .asGrpcStatusFromContext ) @@ -475,7 +475,7 @@ private[kvutils] object TransactionRejections { participantId: String, )(implicit loggingContext: ContextualizedErrorLogger): Status = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.SubmitterCannotActViaParticipant + LedgerApiErrors.WriteServiceRejections.SubmitterCannotActViaParticipant .Reject( details, submitter, @@ -518,7 +518,7 @@ private[kvutils] object TransactionRejections { definiteAnswer: Boolean = false )(implicit loggingContext: ContextualizedErrorLogger): Status = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.DuplicateCommand + LedgerApiErrors.ConsistencyErrors.DuplicateCommand .Reject(definiteAnswer) .asGrpcStatusFromContext ) @@ -567,7 +567,7 @@ private[kvutils] object TransactionRejections { submitter: String )(implicit loggingContext: ContextualizedErrorLogger): Status = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.SubmittingPartyNotKnownOnLedger + LedgerApiErrors.WriteServiceRejections.SubmittingPartyNotKnownOnLedger .Reject(submitter) .asGrpcStatusFromContext ) @@ -576,7 +576,7 @@ private[kvutils] object TransactionRejections { parties: Seq[String] )(implicit loggingContext: ContextualizedErrorLogger): Status = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.PartyNotKnownOnLedger + LedgerApiErrors.WriteServiceRejections.PartyNotKnownOnLedger .Reject(parties.toSet) .asGrpcStatusFromContext ) @@ -596,7 +596,7 @@ private[kvutils] object TransactionRejections { ledger_time_upper_bound: Instant, )(implicit loggingContext: ContextualizedErrorLogger): Status = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.InvalidLedgerTime + LedgerApiErrors.ConsistencyErrors.InvalidLedgerTime .RejectEnriched(details, ledger_time, ledger_time_lower_bound, ledger_time_upper_bound) .asGrpcStatusFromContext ) @@ -606,7 +606,7 @@ private[kvutils] object TransactionRejections { details: String )(implicit loggingContext: ContextualizedErrorLogger): Status = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.PartyNotKnownOnLedger + LedgerApiErrors.WriteServiceRejections.PartyNotKnownOnLedger .RejectDeprecated(details) .asGrpcStatusFromContext ) @@ -616,7 +616,7 @@ private[kvutils] object TransactionRejections { details: String )(implicit loggingContext: ContextualizedErrorLogger): Status = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.Inconsistent + LedgerApiErrors.ConsistencyErrors.Inconsistent .Reject(details) .asGrpcStatusFromContext ) @@ -626,7 +626,7 @@ private[kvutils] object TransactionRejections { details: String )(implicit loggingContext: ContextualizedErrorLogger): Status = GrpcStatus.toProto( - LedgerApiErrors.CommandRejections.Disputed + LedgerApiErrors.WriteServiceRejections.Disputed .Reject(details) .asGrpcStatusFromContext )