Skip to content

[Bug] Error construction leads to StackOverflowException when logging it #773

@jcubells

Description

@jcubells

Neo4j Version: 4.1.3 Community
Neo4j Mode: Single instance
Driver version: Java driver 4.1.1
Operating System: Ubuntu 18

Description of the bug:
When making a request with old syntax like "MATCH(n:Element) WHERE n.name = {param} RETURN n" through the java driver
The driver throws a ClientException

org.neo4j.driver.exceptions.ClientException: The old parameter syntax `{param}` is no longer supported. Please use `$param` instead (line 1, column 34 (offset: 33))
"MATCH (n:Element) WHERE n.name = {param} RETURN n"

This exception has a suppressed exception (ClientException: Transaction can't be committed)
This exception has cause org.neo4j.driver.exceptions.ClientException: The old parameter syntax {param} is no longer supported
.....

This is an infinite reccursion, which leads to Stackoverflow when logging the Exception

Expected behaviour:
There should not be an infinite recursion in the Exception construction

Code sample to reproduce
`private static final Logger LOGGER = LoggerFactory.getLogger(Neo4jBoltClientTest.class);

@Test
public void shouldTerminate() {
    CompletionStage<List<ResultCursor>> listCompletionStage = new TmpClient().executionInTransaction(tx -> Flux.from(
            Mono.fromCompletionStage(
                    tx.runAsync("MATCH (n:Element) WHERE n.name = {param} RETURN n", Map.of("param", "Luke"))
            )
    ));

    List<ResultCursor> block = Mono.fromCompletionStage(listCompletionStage).block();

}

private class TmpClient {

    // here wNeo is a test rule, you can put any database URL. The database doesn't matter much, and the data in it either, since the request can't be executed anyways
    private String url = wNeo.boltURI().toString(); 
    private Driver driver = GraphDatabase.driver(url,
            AuthTokens.basic("neo4j", "neo4j"));

    public <T> CompletionStage<List<T>> executionInTransaction(Function<AsyncTransaction, Flux<T>> txFunction) {
        return driver.asyncSession()
                .writeTransactionAsync(tx -> txFunction.apply(tx).collectList().toFuture())
                .whenComplete((val, thr) -> {
                    try {
                        LOGGER.error("error", thr);
                    } catch (Throwable t) {
                        LOGGER.error("error in log", t); // this will catch a Stackoverflow Exception
                    }
                });
    }
}`

Log output:
18:18:03.998 [main ] INFO Driver - Direct driver instance 814684352 created for server address 127.0.0.1:46295 18:18:14.544 [Neo4jDriverIO-3-3] ERROR c.l.l.n.i.c.Neo4jBoltClientTest - error in log java.lang.StackOverflowError: null at java.base/java.lang.reflect.InvocationTargetException.<init>(InvocationTargetException.java:73) at java.base/jdk.internal.reflect.GeneratedMethodAccessor6.invoke(Unknown Source) at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.base/java.lang.reflect.Method.invoke(Method.java:566) at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:66) at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:60) at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:72) at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:60) at ch.qos.logback.classic.spi.ThrowableProxy.<init>(ThrowableProxy.java:72) .... (lines 60/72 alternate until Stackoverflow)

NOTE: this behaviour doesn't happen with some other syntax errors.
For example, "MATCH(n:ELEMENT)" - which will fail since it has no return or update clause) will return a ClientException without any suppressed exception, thus it can be logged without problems

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions