Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
jcubells opened this issue Oct 23, 2020 · 1 comment · Fixed by #895
Closed

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

jcubells opened this issue Oct 23, 2020 · 1 comment · Fixed by #895
Labels

Comments

@jcubells
Copy link

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

@technige technige added the bug label Oct 26, 2020
@denisftw
Copy link

Hey @technige and @jcubells

I have the same problem with version 4.2.0. It seems that stack overflow happens when someone tries to log an exception with circular suppressed references, and there is a lot more information about it here:

https://jira.qos.ch/browse/LOGBACK-1027

It was fixed in the latest alpha version of Logback 1.3, but since 1.3 is going to require Java 9, many people will be stuck with 1.2.3 for some time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants