Skip to main content

Introduction

This documentation is intended for developers working with our API. It provides an overview of our error handling framework.

Handling Linckr Exceptions

To make Linckr exceptions understandable across all domains, we use the Problem Details standard to format and describe error messages. If an error is thrown during the API request, a Linckr problem detail will be shown (see below for structure). For GraphQL endpoints, problem details are shown in the extension part, and for REST endpoints, they are displayed in the response body.

public interface ProblemDetail {
/**
* The JSON formatted details body of a failing http request.
*
* @see [RFC-7807](https://tools.ietf.org/html/rfc7807)
*/
MediaType JSON_PROBLEM_MEDIA_TYPE = MediaType.APPLICATION_PROBLEM_JSON;
URI DEFAULT_TYPE = URI.create("about:blank");

/**
* @return Relative URI to extensive problem documentation
* Format: /BASE_URL/${code}
* Example: /docs/problems/user-not-found
* Default: about:blank
*/
default URI getType() {
return DEFAULT_TYPE;
}

/**
* @return A short, human-readable summary of the problem type.
* It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization
*/
String getTitle();

/**
* @return An optional human-readable explanation about the problem.
* It SHOULD NOT change from occurrence to occurrence of the problem, except for purposes of localization
*/
default Optional<String> getDetail() {
return Optional.empty();
}

/**
* @return Optional status code
* Always maps the Http-header status
*/
default Optional<HttpStatus> getStatus() {
return Optional.empty();
}

/**
* @return Optional application-specific code. May be used as e.g. a translation key.
* Format: kebab case
* Example: user-not-found
*/
default Optional<LinckrErrorCode> getCode() {
return Optional.empty();
}

/**
* @return Optional instance URI. Uniquely refers to an individual incident of the problem type.
* It may or may not yield further information if dereferenced.
*/
default Optional<URI> getInstance() {
return Optional.empty();
}
}

Error Codes

We utilize error codes to facilitate error communication called the LinckrErrorCode. These codes help render documentation pages for users, determine HTTP status codes, and provide guidance on error handling.

note

most of the documentation pages are not present yet, however will be provided in the future.

Here is a list of codes in the platform:

  • ENTITY_NOT_FOUND_ERROR - This error code is commonly used when an attempt to access or manipulate a specific entity in the system fails because the entity does not exist. For example, if a user tries to retrieve a user profile that doesn't exist, this error might be raised.
  • FILE_NOT_FOUND_ERROR - This error occurs when a requested file or resource cannot be found.
  • EXTERNAL_SYSTEM - This error code indicates a problem related to interactions with external systems or services
  • UNKNOWN - is a generic code used when the specific nature of the error is not known or cannot be classified into a more specific category
  • CONFIGURATION - This error typically arises due to misconfigurations in the application, such as incorrect settings, missing configurations, or invalid environment variables.
  • JSON - error code suggests issues related to parsing or handling JSON data. It might be used when there are problems with JSON structure, encoding, or decoding.
  • RETRY - This code indicates that an operation has failed temporarily, and a retry might succeed. It's often used for transient errors, such as network timeouts, where retrying the operation after a delay is a reasonable strategy.
  • MAPPER_ERROR - occurs when there are problems mapping data between different formats or data models
  • FAILED_RETRY - This code signifies that a previously retried operation has failed even after multiple attempts. It indicates a more persistent issue that requires investigation.
  • VALIDATION_ERROR - is used when input data does not meet the expected criteria or fails validation rules. For instance, if a user submits a form with invalid email format, this error might be raised.
  • BUSINESS_EXCEPTION - This code is used for errors that relate to business logic. It indicates that an operation cannot proceed due to specific business rules or conditions not being met.
  • UNAUTHORIZED - indicates that the request has not been applied because it lacks valid authentication credentials for the target resource
  • FORBIDDEN - used when a user or system has valid authentication but is not permitted to access a particular resource or perform a specific action due to access control restrictions.

Example

Below you can see an example of a GraphQL error response. The part in the extensions contains the Linckr Problem Detail. This will also be shown in the response body of a REST call.

{
"errors": [
{
"message": "OrganisationValidator#doesNotExist: Organisation with following fields does already exists: name: 'testcompany', businessLocationName: 'testcompany', street: 'Nieuwe Stationsstraat', streetNumber: '345', addition: 'null', postalCode:'6811 KS', city: 'Arnhem'!",
"locations": [
{
"line": 5,
"column": 3
}
],
"path": [
"configureNewOrganisation"
],
"extensions": {
"title": "OrganisationValidator#doesNotExist: Organisation with following fields does already exists: name: 'testcompany', businessLocationName: 'testcompany', street: 'Nieuwe Stationsstraat', streetNumber: '345', addition: 'null', postalCode:'6811 KS', city: 'Arnhem'!",
"linckrErrorCode": [
".LinckrGlobalErrorCode",
"VALIDATION_ERROR"
],
"detail": null,
"type": "about:blank",
"instance": null,
"status": "BAD_REQUEST",
"code": "VALIDATION_ERROR",
"classification": "DataFetchingException"
}
}
],
"data": null
}

Improvements

Following errors are not handled yet with a clear problem detail but will be in the future.

input validation errors

The errors regarding graphQL/Rest endpoint input validation are using still the basic errors of the framework itself. For example when you forget a field in the GraphQL query the error will look like this:


{
"errors": [
{
"message": "Validation error (WrongType@[registerTemplate]) : argument 'template' with value 'ObjectValue{objectFields=[ObjectField{name='id', value=StringValue{value='TEST_TEMPLATE'}}, ObjectField{name='type', value=EnumValue{name='DOCUMENT_REQUEST_TEMPLATE'}}, ObjectField{name='cmmnModel', value=StringValue{value='<definitions>\n</definitions>'}}]}' is missing required fields '[names]'",
"locations": [
{
"line": 2,
"column": 22
}
],
"extensions": {
"classification": "ValidationError"
}
}
]
}

Aggregate already exists

This error can happen when you try to register an object that already is an aggregate instance. This means the object is already created. Axon (our event sourcing framework) does not allow you to create two (or more) aggregate instances with the same aggregate identifier. The framework does this so that aggregate event streams never mix, ensuring aggregate events are correctly ordered

In the example below you can see that we tried to create a template called TEST_TEMPLATE 2 times.


{
"errors": [
{
"message": "ResultHandler:lambda$intercept$0: OUT_OF_RANGE: [AXONIQ-2000] Invalid sequence number 0 for aggregate TEST_TEMPLATE, expected 1",
"locations": [
{
"line": 2,
"column": 5
}
],
"path": [
"registerTemplate"
],
"extensions": {
"title": "ResultHandler:lambda$intercept$0: OUT_OF_RANGE: [AXONIQ-2000] Invalid sequence number 0 for aggregate TEST_TEMPLATE, expected 1",
"linckrErrorCode": [
".LinckrGlobalErrorCode",
"UNKNOWN"
],
"detail": null,
"type": "about:blank",
"instance": null,
"status": "INTERNAL_SERVER_ERROR",
"code": "UNKNOWN",
"classification": "DataFetchingException"
}
}
],
"data": null
}