neo4j / graphql

A GraphQL to Cypher query execution layer for Neo4j and JavaScript GraphQL implementations.
https://neo4j.com/docs/graphql-manual/current/
Apache License 2.0
504 stars 149 forks source link

Parameter naming leads to error #4908

Closed svenho closed 7 months ago

svenho commented 7 months ago

Describe the bug This error occured first with @neo4j/graphql v4.4.6 and is still present in v5.2.0.

I experienced the bug within cypher FOREACH loops but probably it is not restricted to this.

It seems to be an issue with the naming of the parameters:

(I can workaround this issue by renaming workProjectDetails to x_workProjectDetails.)

Reproduction I habe a mutation like this (abbreviated):

mutate_TopicContent_Update(
    contentOid: ID!
    content: String!
    authorId: ID!
    workProject: [WorkProjectInput]
    workProjectDetails: String
    isSectionHeadline: Int
    firstMainHeading: String
    learningCardTitle: String
    updated: String
  ): TopicContent
    @cypher(
      statement: """
      MATCH ( u:User { oid: $authorId } )
      MATCH ( tc:TopicContent { oid: $contentOid } )
      OPTIONAL MATCH ( tc ) -[r:WORK_PROJECT]-> ( wp_old )
      DELETE r
      FOREACH ( elem IN $workProject |
              MERGE ( wp:WorkProject { oid: elem.oid, ref: elem.ref } )
              MERGE (wp) -[:OWNER]-> (u)
              MERGE (tc)-[:WORK_PROJECT {projectDetails: $workProjectDetails}]-> (wp) )
      SET tc.content = $content, tc.isSectionHeadline = $isSectionHeadline, tc.firstMainHeading = $firstMainHeading, tc.learningCardTitle = $learningCardTitle, tc.updated = $updated
      WITH tc
      RETURN tc as result
      """
      columnName: "result"
    )

Now I call the mutation like this (in Apollo studio):

mutation Mutate_TopicContent_Update($contentOid: ID!, $content: String!, $authorId: ID!) {
  mutate_TopicContent_Update(contentOid: $contentOid, content: $content, authorId: $authorId) {
    oid
  }
}

Then I get an error like this:

"errors": [
    {
      "message": "Variable `NULLDetails` not defined (line 9, column 56 (offset: 355))\n\"            MERGE (tc)-[:WORK_PROJECT {projectDetails: NULLDetails}]-> (wp) )\"\n                                                        ^",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "mutate_TopicContent_Update"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "stacktrace": [
          "Neo4jError: Variable `NULLDetails` not defined (line 9, column 56 (offset: 355))",
          "\"            MERGE (tc)-[:WORK_PROJECT {projectDetails: NULLDetails}]-> (wp) )\"",
          "                                                        ^",
          "",
          "    at captureStacktrace (/.../node_modules/neo4j-driver-core/lib/result.js:620:17)",
          "    at new Result (/.../node_modules/neo4j-driver-core/lib/result.js:112:23)",
          "    at newCompletedResult (/.../node_modules/neo4j-driver-core/lib/transaction.js:523:12)",
          "    at Object.run (/.../node_modules/neo4j-driver-core/lib/transaction.js:355:20)",
          "    at Transaction.run (/.../node_modules/neo4j-driver-core/lib/transaction.js:181:34)",
          "    at ManagedTransaction.run (/.../node_modules/neo4j-driver-core/lib/transaction-managed.js:54:21)",
          "    at Executor.transactionRun (/.../node_modules/@neo4j/graphql/dist/classes/Executor.js:165:28)",
          "    at /.../node_modules/@neo4j/graphql/dist/classes/Executor.js:151:33",
          "    at TransactionExecutor._safeExecuteTransactionWork (/.../node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:211:26)",
          "    at TransactionExecutor.<anonymous> (/.../node_modules/neo4j-driver-core/lib/internal/transaction-executor.js:198:46)"
        ]
      }
    }
  ]

It's interesting that the parameter within the error appears as NULLDetails.

System:

neo4j-team-graphql commented 7 months ago

Many thanks for raising this bug report @svenho. :bug: We will now attempt to reproduce the bug based on the steps you have provided.

Please ensure that you've provided the necessary information for a minimal reproduction, including but not limited to:

If you have a support agreement with Neo4j, please link this GitHub issue to a new or existing Zendesk ticket.

Thanks again! :pray:

angrykoala commented 7 months ago

This is caused by our @cypher replace method. The param $workProject is replaced before $workProjectDetails, which means that the param $workProjectDetails is interpreted as the parameter $workProject and the string Details after that

This can be solved by sorting the arguments by name length, so we make sure to always replace longer params ($workProjectDetails) before shorter ones ($workProject)