Handling Driver Errors

When executing a Cypher statement, certain exceptions and error cases may arise.

One error could be a transient error that may be resolved if retried, for example a problem connecting to the database instance.

Another type of error could be something more permanent, for example a Syntax Error or a Constraint Error.

In the Neo4j Java Driver, exceptions of type Neo4jException will be thrown by methods that run into failure conditions.

The Neo4jException class extends the native Java RuntimeException, and as such contains a message property that contains detailed information about the error that has occurred.

Error Codes

The Neo4jException also includes a code() method, which provides higher-level information about the query.

Each status code follows the same format, and includes four parts:

Neo.[Classification].[Category].[Title]
(1)        (2)          (3)       (4)
  1. Every Neo4j Error code is prefixed with Neo.

  2. The Classification provides a high-level classification of the error - for example, a client-side error or an error with the database.

  3. The Category provides a higher-level category for the error - for example, a problem with clustering, a procedure or the database schema.

  4. The Title provides specific information about the error that has occurred.

Example Error Codes

Here are some common error codes that you may experience:

  • Neo.ClientError.Procedure.ProcedureCallFailed - Failed to invoke a procedure. See the detailed error description for exact cause.

  • Neo.ClientError.Schema.ConstraintViolation - Added or changed index entry would violate constraint.

  • Neo.ClientError.Security.Forbidden - An attempt was made to perform an unauthorized action.

  • Neo.ClientError.Security.Unauthorized - The client is unauthorized due to authentication failure.

  • Neo.ClientError.Statement.ParameterMissing - The statement refers to a parameter that was not provided in the request.

  • Neo.ClientError.Statement.SyntaxError - The statement contains invalid or unsupported syntax.

  • Neo.TransientError.General.TransactionMemoryLimit - There is not enough memory to perform the current task.

For a comprehensive list of status codes, see Status Codes in the Neo4j Documentation.

Catching Errors

Below is an example of how to catch an error thrown by the Driver. It is best practice to use try and catch blocks to catch any errors that are expected and handle unexpected errors at the service or routing level.

Here is an example of how a constraint violation error, could be handled in the auth service.

java
Example
try (var session = driver.session()) {
  session.writeTransaction(tx -> {
      var res = tx.run("CREATE (u:User {email: $email}) RETURN u",
                       Values.parameters("email", email));
      return res.single().get('u').asMap();
  }); 
} catch(Neo4jException e) {
  if (e.code().equals("Neo.ClientError.Schema.ConstraintValidationFailed")) {
    // System.err.println(e.getMessage()); // Node(33880) already exists with...
    throw new ValidationException("An account already exists with the email address "+email,
     Map.of("email","Email address already taken"));
  }
  throw e;
}

Check Your Understanding

1. Which method is available in the Neo4jException class to provide a unique code of the error message?

  • error.code()

  • error.description()

Hint

Neo4j exceptions include a code property, which provides higher-level information about the query.

Solution

To access the exception code, you should use the error.code property.

2. Which method can we examine to find detailed information about any Exception thrown by the driver?

  • error.getCause()

  • error.getDescription()

  • error.getMessage()

Hint

Neo4j errors include a message property, which provides more detailed information about the error.

Solution

To access the detailed error message, you should call the error.getMessage() method.

Lesson Summary

In this lesson, you have learned how to interpret the errors thrown by the Neo4j Java Driver.

In the next Challenge, you will add a unique constraint to the database and add a try/catch block the register() method to handle the error thrown when the email address is already taken.