GraphQL 500 Internal Server Error : branchRuleCreate mutation

Summary

The GraphQL mutation branchRuleCreate caused a 500 Internal Server Error. The error was triggered due to an undefined method (protected_branches) being called on a nil object. The root cause appears to be related to improper handling of the project_or_group variable, leading to a nil value when attempting to access protected_branches.

Steps to Reproduce

  1. Execute the GraphQL mutation branchRuleCreate as shown below:

    mutation branchRuleCreate($input: BranchRuleCreateInput!) {
      branchRuleCreate(input: $input) {
        branchRule {
          branchProtection {
            allowForcePush
          }
        }
        clientMutationId
        errors
      }
    }
  2. Use the following variables:

    {
      "input": {
        "projectPath": "859",
        "name": "random_string_281"
      }
    }
  3. Observe that the system returns a 500 status code.

Example Project

  • Docker Image: Version 17.4.1-ce

Current Bug Behavior

  • The GraphQL mutation branchRuleCreate results in a 500 Internal Server Error.
  • This indicates a server-side failure rather than an expected user-facing error response.

Expected Correct Behavior

  • The expected result should be:
    • A 200 status code with either:
      • The appropriate result of the mutation or,
      • An error object without causing an internal server failure.

Relevant Logs / Error Details

GraphQL Mutation Query:

"query": "mutation branchRuleCreate($input: BranchRuleCreateInput!) { branchRuleCreate(input: $input) { branchRule { branchProtection { allowForcePush } } clientMutationId errors } }",
"variables": "{\"input\":{\"projectPath\":\"859\", \"name\":\"random_string_281\"}}"

Error Trace:

NoMethodError: undefined method `protected_branches' for nil:NilClass

@protected_branch ||= project_or_group.protected_branches.new(params)
                                        ^^^^^^^^^^^^^^^^^^^

app/services/protected_branches/create_service.rb:29:in `protected_branch'
app/services/protected_branches/create_service.rb:16:in `authorized?'
app/services/protected_branches/create_service.rb:6:in `execute'
app/graphql/mutations/branch_rules/create.rb:25:in `resolve'
graphql (2.3.15) lib/graphql/schema/resolver.rb:121:in `public_send'
graphql (2.3.15) lib/graphql/schema/resolver.rb:121:in `call_resolve'
graphql (2.3.15) lib/graphql/schema/mutation.rb:69:in `call_resolve'
graphql (2.3.15) lib/graphql/schema/resolver.rb:108:in `block (3 levels) in resolve_with_support'
graphql (2.3.15) lib/graphql/schema.rb:1413:in `after_lazy'
graphql (2.3.15) lib/graphql/query.rb:393:in `after_lazy'
graphql (2.3.15) lib/graphql/schema/resolver.rb:96:in `block (2 levels) in resolve_with_support'
graphql (2.3.15) lib/graphql/schema.rb:1413:in `after_lazy'
graphql (2.3.15) lib/graphql/query.rb:393:in `after_lazy'
graphql (2.3.15) lib/graphql/schema/resolver.rb:87:in `block in resolve_with_support'
graphql (2.3.15) lib/graphql/schema.rb:1413:in `after_lazy'
graphql (2.3.15) lib/graphql/query.rb:393:in `after_lazy'
graphql (2.3.15) lib/graphql/schema/resolver.rb:75:in `resolve_with_support'
graphql (2.3.15) lib/graphql/schema/has_single_input_argument.rb:36:in `resolve_with_support'
graphql (2.3.15) lib/graphql/schema/relay_classic_mutation.rb:45:in `resolve_with_support'
graphql (2.3.15) lib/graphql/schema/field.rb:735:in `public_send'
graphql (2.3.15) lib/graphql/schema/field.rb:735:in `block (2 levels) in resolve'
graphql (2.3.15) lib/graphql/schema/field.rb:880:in `block in with_extensions'
graphql (2.3.15) lib/graphql/schema/field.rb:916:in `block (2 levels) in run_extensions_before_resolve'
graphql (2.3.15) lib/graphql/schema/field.rb:916:in `block (2 levels) in run_extensions_before_resolve'
graphql (2.3.15) lib/graphql/schema/field.rb:919:in `run_extensions_before_resolve'
graphql (2.3.15) lib/graphql/schema/field.rb:916:in `block in run_extensions_before_resolve'
graphql (2.3.15) lib/graphql/schema/field_extension.rb:134:in `resolve'
graphql (2.3.15) lib/graphql/schema/field.rb:903:in `run_extensions_before_resolve'
graphql (2.3.15) lib/graphql/schema/field.rb:916:in `block in run_extensions_before_resolve'
lib/gitlab/graphql/present/field_extension.rb:18:in `resolve'
graphql (2.3.15) lib/graphql/schema/field.rb:903:in `run_extensions_before_resolve'
graphql (2.3.15) lib/graphql/schema/field.rb:875:in `with_extensions'
graphql (2.3.15) lib/graphql/schema/field.rb:706:in `block in resolve'
graphql (2.3.15) lib/graphql/schema.rb:1413:in `after_lazy'
graphql (2.3.15) lib/graphql/query.rb:393:in `after_lazy'
graphql (2.3.15) lib/graphql/schema/field.rb:704:in `resolve'
graphql (2.3.15) lib/graphql/execution/interpreter/runtime.rb:375:in `block (2 levels) in evaluate_selection_with_resolved_keyword_args'
graphql (2.3.15) lib/graphql/tracing/trace.rb:52:in `execute_field'
batch-loader (2.0.5) lib/batch_loader/graphql.rb:7:in `execute_field'
graphql (2.3.15) lib/graphql/schema/timeout.rb:84:in `execute_field'
...
Assignee Loading
Time tracking Loading