GRANDStack : Neo4jError: Expected to find a node at ref slot 1 but found Map Error

Hello

When I use and re-use default mutation AddUserFriends, it is translated to CREATE and not MERGE, this way if I fire the same request again, I have always a new RELATION, what I really want is have just one UNIQUE relation, for example one :FRIENDS relation

for this I try to change the CREATE in generated query with MERGE

first I get the original non custom query from logs

MATCH (`user_from`:`User` {id: $from.id})
MATCH (`user_to`:`User` {id: $to.id})
CREATE (`user_from`)-[`friends_relation`:`FRIENDS`]->(`user_to`)
RETURN `friends_relation` { from: `user_from` { .name } ,to: `user_to` { .name }  } AS `_AddUserFriendsPayload`;

I tested it in neo4j browser with :params

:params {"from": { id: "u3" },"to": { id: "u4" }}

and it work has expected

next I create a new custom mutation changing only the CREATE with MERGE, and create the type too for ex

type _AddUserFriendsPayload {
  from: User
  to: User
}

type Mutation {
  AddUserFriends(from: _UserInput!, to: _UserInput!): _AddUserFriendsPayload @cypher(
  statement:"""
    MATCH (`user_from`:`User` {id: $from.id})
    MATCH (`user_to`:`User` {id: $to.id})
    MERGE (`user_from`)-[`friends_relation`:`FRIENDS`]->(`user_to`)
    RETURN `friends_relation` { from: `user_from` { .name } ,to: `user_to` { .name }  } AS `_AddUserFriendsPayload`;
  """)     
}

I compared the docs with and without custom mutation, and mutation and type are equal......

fire the mutation, the same mutation that works without custom mutation

mutation ($from: _UserInput!, $to: _UserInput!) {
  AddUserFriends(from: $from, to: $to ) {
    from {
      name
    }
    to {
      name
    }
  }
}

with query variables

{ 
  "from": { "id": "u3" }, 
  "to": { "id": "u4" }
}

I always have the result

{
  "errors": [
    {
      "message": "Expected to find a node at ref slot 1 but found Map{from -> Map{name -> String(\"Jenny\")}, to -> Map{name -> String(\"Angie\")}} instead",
      "locations": [
        {
          "line": 2,
          "column": 3
        }
      ],
      "path": [
        "AddUserFriends"
      ],
      "extensions": {
        "code": "INTERNAL_SERVER_ERROR",
        "exception": {
          "code": "Neo.ClientError.Statement.TypeError",
          "name": "Neo4jError",
          "stacktrace": [
            "Neo4jError: Expected to find a node at ref slot 1 but found Map{from -> Map{name -> String(\"Jenny\")}, to -> Map{name -> String(\"Angie\")}} instead",
            "",
            "    at captureStacktrace (/media/mario/Storage/Development/Node/NodeGrandStackStarter/api/node_modules/neo4j-driver/lib/v1/result.js:200:15)",
            "    at new Result (/media/mario/Storage/Development/Node/NodeGrandStackStarter/api/node_modules/neo4j-driver/lib/v1/result.js:73:19)",
            "    at _newRunResult (/media/mario/Storage/Development/Node/NodeGrandStackStarter/api/node_modules/neo4j-driver/lib/v1/transaction.js:344:10)",
            "    at Object.run (/media/mario/Storage/Development/Node/NodeGrandStackStarter/api/node_modules/neo4j-driver/lib/v1/transaction.js:253:14)",
            "    at Transaction.run (/media/mario/Storage/Development/Node/NodeGrandStackStarter/api/node_modules/neo4j-driver/lib/v1/transaction.js:122:26)",
            "    at /media/mario/Storage/Development/Node/NodeGrandStackStarter/api/node_modules/neo4j-graphql-js/dist/index.js:71:25",
            "    at TransactionExecutor._safeExecuteTransactionWork (/media/mario/Storage/Development/Node/NodeGrandStackStarter/api/node_modules/neo4j-driver/lib/v1/internal/transaction-executor.js:136:22)",
            "    at TransactionExecutor._executeTransactionInsidePromise (/media/mario/Storage/Development/Node/NodeGrandStackStarter/api/node_modules/neo4j-driver/lib/v1/internal/transaction-executor.js:124:32)",
            "    at /media/mario/Storage/Development/Node/NodeGrandStackStarter/api/node_modules/neo4j-driver/lib/v1/internal/transaction-executor.js:67:15",
            "    at new Promise (<anonymous>)"
          ]
        }
      }
    }
  ],
  "data": {
    "AddUserFriends": null
  }
}

log result

CALL apoc.cypher.doIt("MATCH (`user_from`:`User` {id: $from.id})
MATCH (`user_to`:`User` {id: $to.id})
CREATE (`user_from`)-[`friends_relation`:`FRIENDS`]->(`user_to`)
RETURN `friends_relation` { from: `user_from` { .name } ,to: `user_to` { .name }  } AS `_AddUserFriendsPayload`;", {from:$from, to:$to, first:$first, offset:$offset}) YIELD value
    WITH apoc.map.values(value, [keys(value)[0]])[0] AS `_AddUserFriendsPayload`
    RETURN `_AddUserFriendsPayload` {from: head([(`_AddUserFriendsPayload`)<-[`_AddUserFriendsPayload_from_relation`:`__ADD_USER_FRIENDS_PAYLOAD`]-(`_AddUserFriendsPayload_from`:`User`) | _AddUserFriendsPayload_from_relation { .name }]) ,to: head([(`_AddUserFriendsPayload`)-[`_AddUserFriendsPayload_to_relation`:`__ADD_USER_FRIENDS_PAYLOAD`]->(`_AddUserFriendsPayload_to`:`User`) | _AddUserFriendsPayload_to_relation { .name }]) } AS `_AddUserFriendsPayload`
{
  "from": {
    "id": "u3"
  },
  "to": {
    "id": "u4"
  },
  "first": -1,
  "offset": 0
}

if I copy the query in above log, and use it in neo4 it works

MATCH (`user_from`:`User` {id: $from.id})
MATCH (`user_to`:`User` {id: $to.id})
CREATE (`user_from`)-[`friends_relation`:`FRIENDS`]->(`user_to`)
RETURN `friends_relation` { from: `user_from` { .name } ,to: `user_to` { .name }  } AS `_AddUserFriendsPayload`

returns

{
  "from": {
    "name": "Jenny"
  },
  "to": {
    "name": "Angie"
  }
}

after avoid some errors, I ended here, and I don't know what I require to create/replicate a custom mutation, just to learn how too use custom mutations and exchange CREATE with MERGE

another thing I think that make sense is use by default MERGE and not CREATE to this kind of stuff, this will prevent some duplication, but is just my humble opinion

maybe is a way to do it, and I don't know how.......

I read all the docs and topics in this channel but I can't find any help

UPDATE: the problem is relates with RETURN......but if I change RETURN to return the nodes with

RETURN `friends_relation` { from: `user_from`, to: `user_to` } AS `_AddUserFriendsPayload`;

the error message changes to

"message": "Expected to find a node at ref slot 1 but found Map{from -> (21), to -> (22)} instead"

where 21 and 22 are the id's......................it sems that info fields from payload are not passed to query ex { .name }....

thanks

ps: awsome work @William_Lyon and @michael.hunger ,
I really like your work and neo4j,
you really do a lot for neo4j community, thanks

1 Like

it seems that nothing happens here...
time will tell, patience is virtue :)

UP. topic

Hi @marioammonteiro,

I was having a very similar problem. I wanted to MERGE instead of CREATE and my return was causing the error you describe: Expected to find a node at ref slot <some number> but found Map...

I'm still new to Neo4j/cypher/GraphQL, and I don't know if this is the ideal answer, but I was able to solve this by creating a completely new mutation, input, and payload for my query. For the input and return, the important part for me was to use a single object with no nested objects. I think this is because there was a lot of auto-generated types that weren't playing well together downstream.

You could try something like:

input CreateUserAndFriendInput {
    userProp: String!
    friendProp: String!
}

type CreateUserAndFriendPayload {
    userProp: String
    friendProp: String
}

type Mutation {
    CreateUserAndFriend(input: CreateUserAndFriendInput!): CreateUserAndFriendPayload
    @cypher(statement:"""
    MERGE(user:User { userProp: input.userProp })-[:FRIENDS]->(friend:User { friendProp: input.friendProp })
    RETURN { userProp: user.userProp, friendProp: friend.friendProp }
    """)
}

Then be sure to exclude the CreateUserAndFriendPayload from your auto-generated queries and mutations, as seen here

1 Like

Thanks @dnllowe

I return to neo4j/graphql project yesterday
And only ser your answear right now

I will try it ASAP and leave ver the feedback

Once again thanks m8