apoc icon indicating copy to clipboard operation
apoc copied to clipboard

apoc.path.combine(path,path1) as paths throws Can't coerce `NO_VALUE` to Path error in linux

Open neo-technology-build-agent opened this issue 3 years ago • 10 comments

Issue by shahadp Tuesday Feb 25, 2020 at 19:57 GMT Originally opened as https://github.com/neo4j-contrib/neo4j-apoc-procedures/issues/1427


Guidelines

Please note that GitHub issues are only meant for bug reports/feature requests. If you have questions on how to use APOC, please ask on the Neo4j Discussion Forum instead of creating an issue here.

Expected Behavior (Mandatory)

apoc.convert.toTree(paths) return valid json response.

Actual Behavior (Mandatory)

Returns error. Neo.ClientError.Statement.TypeError . Can't coerce NO_VALUE to Path

How to Reproduce the Problem

The below issue happens in linux redhat linux neo4j V4.0.0 enterprise & windows V4.0.0 enterprise
Create a category name it root. create sub_category relation subcategory node under that category (this can run into different depth). create products under subcategory. This happens only if you have sub_Category that dont have any product under that and some sub_category have some products match path= (c:Category)-[:SUB_CATEGORY*]->(sc:SubCategory) optional match path1= (sc)-[:PRODUCT*]->(p:product) WITH apoc.path.combine(path,path1) as path0 with collect (path0) as paths call apoc.convert.toTree(paths) yield value return value

Simple Dataset (where it's possibile)

//Insert here a set of Cypher statements that helps us to reproduce the problem
match path= (c:Category)-[:SUB_CATEGORY*]->(sc:SubCategory)
optional match path1= (sc)-[:PRODUCT*]->(p:product)
 WITH apoc.path.combine(path,path1) as path0 with collect (path0) as paths call apoc.convert.toTree(paths) yield value return value


### Steps (Mandatory)

  1. Run the above cypher couple of times using browser, the error should appear with in 5-10 execution or repeat until it reproduces. 
  1.
  1.

## Screenshots (where it's possibile)
The below query executes 5 times fine and six time returns an error  Neo.ClientError.Statement.TypeError .
Can't coerce `NO_VALUE` to Path

Until next restart it wont work.
match path= (c:Category)-[:SUB_CATEGORY*]->(sc:SubCategory)
optional match path1= (sc)-[:PRODUCT*]->(p: product)
 WITH apoc.path.combine(path,path1) as path0 with collect (path0) as paths call apoc.convert.toTree(paths) yield value return value

return paths works well, it seems apoc.convert.toTree() yield value may be having some issue not sure . after 5 execution it just returns this error can't coerce .. 

## Specifications (Mandatory)
it seems apoc.convert.toTree() yield value may be having some issue not sure . after 5 execution it just returns this error can't coerce

Currently used versions

### Versions

  - OS: Red Hat Enterprise Linux 8 (HVM), windows 2016 server
  - Neo4j: neo4j V4.0.0 enterprise 
  - Neo4j-Apoc: 4.0.0.4

### Error details from query.log

org.neo4j.exceptions.CypherTypeException: Can't coerce `NO_VALUE` to Path
	at org.neo4j.cypher.operations.CypherCoercions.cantCoerce(CypherCoercions.java:287)
	at org.neo4j.cypher.operations.CypherCoercions.asPathValue(CypherCoercions.java:136)
	at org.neo4j.codegen.Expression46/0x0000000101de1c40.project(Unknown Source)
	at org.neo4j.cypher.internal.runtime.slotted.expressions.CompileWrappingProjection.project(CompiledExpressionConverter.scala:160)
	at org.neo4j.cypher.internal.runtime.pipelined.operators.ProjectOperator.operate(ProjectOperator.scala:41)
	at org.neo4j.cypher.internal.runtime.pipelined.operators.OperatorTask.operateWithProfile(Operator.scala:251)
	at org.neo4j.cypher.internal.runtime.pipelined.operators.OperatorTask.operateWithProfile$(Operator.scala:241)
	at org.neo4j.cypher.internal.runtime.pipelined.operators.ProjectOperator.operateWithProfile(ProjectOperator.scala:23)
	at org.neo4j.cypher.internal.runtime.pipelined.PipelineTask.executeOperators(PipelineTask.scala:65)
	at org.neo4j.cypher.internal.runtime.pipelined.PipelineTask.executeWorkUnit(PipelineTask.scala:48)
	at org.neo4j.cypher.internal.runtime.pipelined.Worker.executeTask(Worker.scala:128)
	at org.neo4j.cypher.internal.runtime.pipelined.Worker.workOnQuery(Worker.scala:84)
	at org.neo4j.cypher.internal.runtime.pipelined.execution.CallingThreadExecutingQuery.request(CallingThreadExecutingQuery.scala:30)
	at org.neo4j.cypher.internal.PipelinedRuntime$PipelinedRuntimeResult.request(PipelinedRuntime.scala:326)
	at org.neo4j.cypher.internal.result.StandardInternalExecutionResult.request(StandardInternalExecutionResult.scala:88)
	at org.neo4j.cypher.internal.result.ClosingExecutionResult.request(ClosingExecutionResult.scala:135)
	at org.neo4j.bolt.runtime.AbstractCypherAdapterStream.handleRecords(AbstractCypherAdapterStream.java:105)
	at org.neo4j.bolt.v3.messaging.ResultHandler.onPullRecords(ResultHandler.java:41)
	at org.neo4j.bolt.v4.messaging.PullResultConsumer.consume(PullResultConsumer.java:42)
	at org.neo4j.bolt.runtime.statemachine.impl.TransactionStateMachine$State.consumeResult(TransactionStateMachine.java:511)
	at org.neo4j.bolt.runtime.statemachine.impl.TransactionStateMachine$State$2.streamResult(TransactionStateMachine.java:355)
	at org.neo4j.bolt.runtime.statemachine.impl.TransactionStateMachine.streamResult(TransactionStateMachine.java:92)
	at org.neo4j.bolt.v4.runtime.InTransactionState.processStreamResultMessage(InTransactionState.java:73)
	at org.neo4j.bolt.v4.runtime.AbstractStreamingState.processUnsafe(AbstractStreamingState.java:49)
	at org.neo4j.bolt.v4.runtime.InTransactionState.processUnsafe(InTransactionState.java:60)
	at org.neo4j.bolt.v3.runtime.FailSafeBoltStateMachineState.process(FailSafeBoltStateMachineState.java:48)
	at org.neo4j.bolt.runtime.statemachine.impl.AbstractBoltStateMachine.nextState(AbstractBoltStateMachine.java:143)
	at org.neo4j.bolt.runtime.statemachine.impl.AbstractBoltStateMachine.process(AbstractBoltStateMachine.java:91)
	at org.neo4j.bolt.messaging.BoltRequestMessageReader.lambda$doRead$1(BoltRequestMessageReader.java:90)
	at org.neo4j.bolt.runtime.DefaultBoltConnection.lambda$enqueue$0(DefaultBoltConnection.java:151)
	at org.neo4j.bolt.runtime.DefaultBoltConnection.processNextBatchInternal(DefaultBoltConnection.java:240)
	at org.neo4j.bolt.runtime.DefaultBoltConnection.processNextBatch(DefaultBoltConnection.java:175)
	at org.neo4j.bolt.runtime.DefaultBoltConnection.processNextBatch(DefaultBoltConnection.java:165)
	at org.neo4j.bolt.runtime.scheduling.ExecutorBoltScheduler.executeBatch(ExecutorBoltScheduler.java:212)
	at org.neo4j.bolt.runtime.scheduling.ExecutorBoltScheduler.lambda$scheduleBatchOrHandleError$2(ExecutorBoltScheduler.java:195)
	at java.base/java.util.concurrent.CompletableFuture$AsyncSupply.run(CompletableFuture.java:1700)
	at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1128)
	at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:628)
	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
	at java.base/java.lang.Thread.run(Thread.java:834)


Comment by jexp Wednesday Feb 26, 2020 at 10:15 GMT


does this also happen if you pass an empty list or a null value to toTree

Comment by shahadp Wednesday Feb 26, 2020 at 10:57 GMT


Passing empty list provides this response {

} Passing null provides this resopnse Failed to invoke procedure apoc.convert.toTree: Caused by: java.lang.NullPointerException Please note this was working fine in v3.5.14 with apoc version apoc-3.5.0.5-all. Also after restart first 5 invocations work fine and 6th one onwards fails until restart or by modifying some values in cypher (like adding a relationship name makes it work again for 5 times and fails at 6th time- sometimes 4 and fails at 5th. Its a definte pattern).

Also happens only if use optional keyword ( means i have to pull the subcategory with no products under it as its not filled with product yet)

Comment by shahadp Thursday Feb 27, 2020 at 00:50 GMT


After doing some more research on this subject it seems its not cause by apoc.covert.toTree, it is apoc.path.combine issue after 5 or 6 successful execution.

Th below query does not work---> match path= (c:Category)-[:SUB_CATEGORY*]->(sc:SubCategory)optional match path1= (sc)-[:PRODUCT*]->(p:Product) WITH apoc.path.combine(path,path1) as path0 return path0 -->This does not work after 5 or 6 executions--> Exception::org.neo4j.driver.exceptions.ClientException: Can't coerce NO_VALUE to Path

The below query works---> so path, path1 are retrieved successfully. match path= (c:Category)-[r:SUB_CATEGORY*]->(sc:SubCategory) optional match path1= (sc)-[r1:PRODUCT*]->(p:Product) return path,path1

Comment by jexp Friday Feb 28, 2020 at 15:06 GMT


Can you check the values returned on repeated execution of the working query that returns path1 and path2? If any of those is null?

Comment by shahadp Monday Mar 02, 2020 at 21:41 GMT


path1 dont have any null value, but path2 because its optional match it will have some null values against the subcategory that dont have a product defined. Another environment details is i upgraded the datastore from 3.5.14 to 4.0 using database upgrade option. to verify the issue i also took a dumb and uploaded in a new datastore but still have the issue. Right now i found a work around to work on the issue by using apoc.path.expand. if i derive my path2 using apoc.path.expand by giving the start node it seems apoc.path.combine is not having any issue.

match path1= (c:Category)-[:SUB_CATEGORY*]->(sc:SubCategory) call apoc.path.expand(sc,'PRODUCT','Product',0,1) YIELD path as path2 WITH apoc.path.combine(path1,path2) as paths return paths

Comment by shahadp Monday Mar 09, 2020 at 18:25 GMT


The issue is getting replicated in lots of places (for 4.0) and queries which previously worked with V3.5. I can see the pattern now its related to null. If there any operation related to null (optional match returns ) for e.g you have couple of values that require multiplication on a certain value.. so let us say we have 5 nodes, 3 having values (size as attribute name) and 2 having null values. size * 1.05 for all 5 nodes, it returns for 5 execution correct response and 6th one as below error. . I can see this pattern related to null and any complex dataset having null combination having this issue.

Comment by cchukuigwe Thursday Mar 19, 2020 at 14:57 GMT


I can confirm that this is still happening in v4.0 on OPTIONAL MATCH returning null results. Exactly as described. Executes first few times then gives similar error as above:

neo4j.exceptions.ClientError: Failed to invoke procedure apoc.cypher.run: Caused by: org.neo4j.exceptions.CypherTypeException: Can't coerce NO_VALUE to Map

Comment by InverseFalcon Tuesday Jul 28, 2020 at 20:08 GMT


As a workaround, we can use CASE as a safeguard to avoid the call if the optional value is null:

match path= (c:Category)-[:SUB_CATEGORY*]->(sc:SubCategory)
optional match path1= (sc)-[:PRODUCT*]->(p:Product) 
WITH CASE WHEN path1 IS NOT NULL THEN apoc.path.combine(path,path1) ELSE path END as path0 
return path0

Comment by shahadp Tuesday Jul 28, 2020 at 22:34 GMT


Hi @InverseFalcon,

Thanks for the update really appreciated, that is exactly what i am doing to avoid the issue at the moment. With the new version (4.x) there are strange issues with cyphers that were previously working with 3.X version with zero issues.

Comment by tanvp112 Friday Aug 21, 2020 at 10:50 GMT


As a workaround, we can use CASE as a safeguard to avoid the call if the optional value is null:

match path= (c:Category)-[:SUB_CATEGORY*]->(sc:SubCategory)
optional match path1= (sc)-[:PRODUCT*]->(p:Product) 
WITH CASE WHEN path1 IS NOT NULL THEN apoc.path.combine(path,path1) ELSE path END as path0 
return path0

Hi InverseFalcon,

When tried with the suggestion with the apoc.path.combine example (https://neo4j.com/labs/apoc/4.1/graph-querying/path-querying/#path-functions-examples), the return result is not the same as the documentation stated.

MATCH (club:Club) OPTIONAL MATCH path1 = (club)-[:IN_LEAGUE]->(league) OPTIONAL MATCH path2 = (league)-[:IN_COUNTRY]->(country) WITH club, path1, path2 WHERE path1 IS NOT NULL and path2 IS NOT NULL // check for invalid path RETURN club.name, apoc.path.combine(path1, path2) AS path ORDER BY length(path)

Not sure if this is regression issue or the documented result is incorrect.

Thanks.

I am unable to reproduce the original bug in this issue, so will close due to that. If someone has a similar issue, with a reproducible data set, feel free to reopen.

As for the above question about the docs, you need to use OR not AND in the null check :)

gem-neo4j avatar Jan 02 '25 13:01 gem-neo4j