dgraph-io / dgraph-io/dgraph

[BUG]: Deep update should not be possible if mandatory fields are not present in the input

Open
#8,781 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

area/graphql community kind/bug Stale status/accepted
Dominant language
Go
Stars
21.8k
Forks
1.6k
Avg merge
2d 5h
Merged PRs (30d)
9

Description

What version of Dgraph are you using?

v22.0.2

Tell us a little more about your go-environment?

I'm using the standalone docker image

Have you tried reproducing the issue with the latest release?

Yes

What is the hardware spec (RAM, CPU, OS)?

not relevant

What steps will reproduce the bug?

schema:

type Project {
  id: ID!
  members: [Member!]
}

type Member {
  id: ID!
  nickname: String!
  favoriteColor: String!
  project: Project! @hasInverse(field: members)
}

Perform deep (nested) update:

mutation UpdateProject($input: UpdateProjectInput!) {
  updateProject(input: $input) {
    project {
      id
      members {
        id
      }
    }
  }
}
{
  "input": {
    "filter": {
      "id": [
        "0x42074"
      ]
    },
    "set": {
      "members": [
        {
          "favoriteColor": "orangey red" // nickname should be here too as it is a required field
        }
      ]
    }
  }
}

result:

{
  "data": {
    "updateProject": {
      "project": [
        {
          "id": "0x42074",
          "members": [
            {
              "id": "0x325aa2"
            }
          ]
        }
      ]
    }
  },
  "extensions": {
    "touched_uids": 22,
    "tracing": {
      "version": 1,
      "startTime": "2023-04-03T23:52:32.2684963Z",
      "endTime": "2023-04-03T23:52:32.3478531Z",
      "duration": 79356900,
      "execution": {
        "resolvers": [
          {
            "path": [
              "updateProject"
            ],
            "parentType": "Mutation",
            "fieldName": "updateProject",
            "returnType": "UpdateProjectPayload",
            "startOffset": 266200,
            "duration": 79044100,
            "dgraph": [
              {
                "label": "preMutationQuery",
                "startOffset": 0,
                "duration": 0
              },
              {
                "label": "mutation",
                "startOffset": 563900,
                "duration": 28755000
              },
              {
                "label": "query",
                "startOffset": 39370300,
                "duration": 39924500
              }
            ]
          }
        ]
      }
    }
  }
}

Query Members

query QueryMember($filter: MemberFilter) {
  queryMember(filter: $filter) {
    id
    source
  }
}

result:

{
  "errors": [
    {
      "message": "Non-nullable field 'nickname' (type String!) was not present in result from Dgraph.  GraphQL error propagation triggered.",
      "locations": [
        {
          "line": 9,
          "column": 5
        }
      ],
      "path": [
        "queryMember",
        0,
        "source"
      ]
    },
    {
      "message": "Non-nullable field 'nickname' (type String!) was not present in result from Dgraph.  GraphQL error propagation triggered.",
      "locations": [
        {
          "line": 9,
          "column": 5
        }
      ],
      "path": [
        "queryMember",
        1,
        "nickname"
      ]
    }
  ],
  "data": {
    "queryMember": [
      null,
      null
    ]
  },
  "extensions": {
    "touched_uids": 13,
    "tracing": {
      "version": 1,
      "startTime": "2023-04-03T23:58:15.1985333Z",
      "endTime": "2023-04-03T23:58:15.2292826Z",
      "duration": 30749300,
      "execution": {
        "resolvers": [
          {
            "path": [
              "queryMember"
            ],
            "parentType": "Query",
            "fieldName": "queryMember",
            "returnType": "[Member]",
            "startOffset": 647000,
            "duration": 29973700,
            "dgraph": [
              {
                "label": "query",
                "startOffset": 880400,
                "duration": 29730700
              }
            ]
          }
        ]
      }
    }
  }
}
Expected behavior and actual result.

Attempting to create a nested object via a deep update should fail/error if required/mandatory field values are not present in the mutation variables. Without this, it is easy to corrupt the data via user error.

Additional information

No response

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start by reproducing the nested updateProject mutation with the Project and Member schema shown, then inspect the GraphQL update path and its handling of required fields. Done means the mutation rejects a nested Member that omits nickname or another mandatory field, while valid nested updates continue to work.

Written by the indexing model from the issue text.

Assessment

Tech stack
docker, go, graphql
Domain
api, databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.