Repository: 99designs/gqlgen
Pull request #3614 (2025-03-25 00:57:28)

Update to golangci-lint v2
This updates [golangci-lint to v2](https://ldez.github.io/blog/2025/03/23/golangci-lint-v2/) by running `golangci-lint migrate` and then 🤞
...
❌  😞 
so I then ran:
```
golangci-lint run --fix --config=.golangci.yml ./...
go generate ./...
```
And added a few `//nolint` comments around newlines. I still had to disable the revive `usa-any` rule because it wasn't ignoring some of the the generated resolver `map[string]interface{}`  code.

Signed-off-by: Steve Coffman <steve@khanacademy.org>


coveralls: 
[![Coverage Status](https://coveralls.io/builds/72900148/badge)](https://coveralls.io/builds/72900148)

coverage: 73.465% (-0.03%) from 73.49%
when pulling **9cda62ff969f9773f64b3cd654b975c8fa84af46 on golangci-lint-v2**
into **7f0d34534e21965a2c5983b9abae8375a9dca018 on master**.


Patch:
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index 3ef13da5..72b03717 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -5,17 +5,18 @@ on:
       - master
   pull_request:
     types: [ opened, synchronize ]
-env:
-  GOTOOLCHAIN: local
 # When a new revision is pushed to a PR, cancel all in-progress CI runs for that
 # PR. See https://docs.github.com/en/actions/using-jobs/using-concurrency
 concurrency:
   group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
   cancel-in-progress: true
+env:
+  GOTOOLCHAIN: local
+  GOFLAGS: "-trimpath"
 jobs:
   golangci-lint:
     env:
-      GOLANGCI_LINT_VERSION: v1.64.5
+      GOLANGCI_LINT_VERSION: latest
     strategy:
       matrix:
         go: ["1.23", "1.24"]
@@ -26,11 +27,11 @@ jobs:
         with:
           go-version: ${{ matrix.go }}
       - name: golangci-lint
-        uses: golangci/golangci-lint-action@v6.5.2
+        uses: golangci/golangci-lint-action@v7.0.0
         with:
           version: ${{ env.GOLANGCI_LINT_VERSION }}
       - name: golangci-lint examples
-        uses: golangci/golangci-lint-action@v6.5.2
+        uses: golangci/golangci-lint-action@v7.0.0
         with:
           version: ${{ env.GOLANGCI_LINT_VERSION }}
           working-directory: _examples
diff --git a/.golangci.yml b/.golangci.yml
index 04424693..cdd594f6 100644
--- a/.golangci.yml
+++ b/.golangci.yml
@@ -1,84 +1,8 @@
+version: "2"
 run:
   tests: true
-  timeout: 5m
-
-linters-settings:
-  gocritic:
-    enabled-checks:
-      - emptyStringTest
-      - equalFold
-      - httpNoBody
-      - nilValReturn
-      - paramTypeCombine
-      - preferFprint
-      - yodaStyleExpr
-  govet:
-    enable-all: true
-    disable:
-      - fieldalignment
-      - shadow
-      - unusedwrite # TODO: fix and enable
-  errcheck:
-    exclude-functions:
-      - (io.Writer).Write
-      - io.Copy
-      - io.WriteString
-  perfsprint:
-    int-conversion: false
-    err-error: false
-    errorf: true
-    sprintf1: false
-    strconcat: false
-  revive:
-    enable-all-rules: false
-    rules:
-      - name: empty-lines
-      - name: use-any
-      - name: struct-tag
-      - name: blank-imports
-      - name: context-as-argument
-      - name: context-keys-type
-      - name: error-return
-      - name: error-naming
-      - name: exported
-        disabled: true
-      - name: if-return
-      - name: increment-decrement
-      - name: var-declaration
-      - name: package-comments
-        disabled: true
-      - name: range
-      - name: receiver-naming
-      - name: time-naming
-      - name: unexported-return
-      - name: indent-error-flow
-      - name: errorf
-      - name: superfluous-else
-      - name: unused-parameter
-        disabled: true
-      - name: unreachable-code
-      - name: redefines-builtin-id
-  testifylint:
-    disable-all: true
-    enable:
-      - blank-import
-      - bool-compare
-      - compares
-      - empty
-      - encoded-compare
-      - error-is-as
-      - error-nil
-      - expected-actual
-      - float-compare
-      - go-require
-      - len
-      - negative-positive
-      - nil-compare
-      - require-error
-      - useless-assert
-
 linters:
-  disable-all: true
+  default: none
   enable:
     - bodyclose
     - copyloopvar
@@ -86,9 +10,6 @@ linters:
     - dupword
     - errcheck
     - gocritic
-    - gofmt
-    - goimports
-    - gosimple
     - govet
     - ineffassign
     - misspell
@@ -101,36 +22,125 @@ linters:
     - testifylint
     - unconvert
     - unused
-
-issues:
-  exclude-dirs:
-    - bin
-  exclude-rules:
-    # Exclude some linters from running on tests files.
-    - path: _test\.go
-      linters:
-        - dupl
-        - errcheck
-    # It's autogenerated code.
-    - path: codegen/testserver/.*/resolver\.go
-      linters:
-        - gocritic
-    # The interfaces are autogenerated and don't conform to the paramTypeCombine rule
-    - path: _examples/federation/products/graph/entity.resolvers.go
-      linters:
-        - gocritic
-    # Disable revive.use-any for backwards compatibility
-    - path: graphql/map.go
-      text: "use-any: since GO 1.18 'interface{}' can be replaced by 'any'"
-    - path: codegen/testserver/followschema/resolver.go
-      text: "use-any: since GO 1.18 'interface{}' can be replaced by 'any'"
-    - path: codegen/testserver/singlefile/resolver.go
-      text: "use-any: since GO 1.18 'interface{}' can be replaced by 'any'"
-    - path: codegen/testserver/generated_test.go
-      linters:
-        - staticcheck
-      text: SA1019
-    - path: plugin/modelgen/models_test.go
-      linters:
-        - staticcheck
-      text: SA1019
+  settings:
+    errcheck:
+      exclude-functions:
+        - (io.Writer).Write
+        - io.Copy
+        - io.WriteString
+    gocritic:
+      enabled-checks:
+        - emptyStringTest
+        - equalFold
+        - httpNoBody
+        - nilValReturn
+        - paramTypeCombine
+        - preferFprint
+        - yodaStyleExpr
+    govet:
+      disable:
+        - fieldalignment
+        - shadow
+        - unusedwrite
+      enable-all: true
+    perfsprint:
+      int-conversion: false
+      err-error: false
+      errorf: true
+      sprintf1: false
+      strconcat: false
+    revive:
+      enable-all-rules: false
+      rules:
+        - name: empty-lines
+#        - name: use-any # this causes problems in some generated files
+        - name: struct-tag
+        - name: blank-imports
+        - name: context-as-argument
+        - name: context-keys-type
+        - name: error-return
+        - name: error-naming
+        - name: exported
+          disabled: true
+        - name: if-return
+        - name: increment-decrement
+        - name: var-declaration
+        - name: package-comments
+          disabled: true
+        - name: range
+        - name: receiver-naming
+        - name: time-naming
+        - name: unexported-return
+        - name: indent-error-flow
+        - name: errorf
+        - name: superfluous-else
+        - name: unused-parameter
+          disabled: true
+        - name: unreachable-code
+        - name: redefines-builtin-id
+    testifylint:
+      disable-all: true
+      enable:
+        - blank-import
+        - bool-compare
+        - compares
+        - empty
+        - encoded-compare
+        - error-is-as
+        - error-nil
+        - expected-actual
+        - float-compare
+        - go-require
+        - len
+        - negative-positive
+        - nil-compare
+        - require-error
+        - useless-assert
+  exclusions:
+    generated: lax
+    presets:
+      - comments
+      - common-false-positives
+      - legacy
+      - std-error-handling
+    rules:
+      - linters:
+          - dupl
+          - errcheck
+        path: _test\.go
+      - linters:
+          - gocritic
+        path: codegen/testserver/.*/resolver\.go
+      - linters:
+          - gocritic
+        path: _examples/federation/products/graph/entity.resolvers.go
+      - path: graphql/map.go
+        text: 'use-any: since GO 1.18 ''interface{}'' can be replaced by ''any'''
+      - path: codegen/testserver/followschema/resolver.go
+        text: 'use-any: since GO 1.18 ''interface{}'' can be replaced by ''any'''
+      - path: codegen/testserver/singlefile/resolver.go
+        text: 'use-any: since GO 1.18 ''interface{}'' can be replaced by ''any'''
+      - linters:
+          - staticcheck
+        path: codegen/testserver/generated_test.go
+        text: SA1019
+      - linters:
+          - staticcheck
+        path: plugin/modelgen/models_test.go
+        text: SA1019
+    paths:
+      - bin
+      - third_party$
+      - builtin$
+      - examples$
+formatters:
+  enable:
+    - gofmt
+    - goimports
+  exclusions:
+    generated: lax
+    paths:
+      - bin
+      - third_party$
+      - builtin$
+      - examples$
diff --git a/codegen/data.go b/codegen/data.go
index c5c3fcc6..d3d8cd89 100644
--- a/codegen/data.go
+++ b/codegen/data.go
@@ -180,11 +180,11 @@ func BuildData(cfg *config.Config, plugins ...any) (*Data, error) {
 	s.ReferencedTypes = b.buildTypes()
 
 	sort.Slice(s.Objects, func(i, j int) bool {
-		return s.Objects[i].Definition.Name < s.Objects[j].Definition.Name
+		return s.Objects[i].Name < s.Objects[j].Name
 	})
 
 	sort.Slice(s.Inputs, func(i, j int) bool {
-		return s.Inputs[i].Definition.Name < s.Inputs[j].Definition.Name
+		return s.Inputs[i].Name < s.Inputs[j].Name
 	})
 
 	if b.Binder.SawInvalid {
diff --git a/codegen/field.go b/codegen/field.go
index c3870592..7fb36ebb 100644
--- a/codegen/field.go
+++ b/codegen/field.go
@@ -481,9 +481,9 @@ func (f *Field) GoNameUnexported() string {
 func (f *Field) ShortInvocation() string {
 	caser := cases.Title(language.English, cases.NoLower)
 	if f.Object.Kind == ast.InputObject {
-		return fmt.Sprintf("%s().%s(ctx, &it, data)", caser.String(f.Object.Definition.Name), f.GoFieldName)
+		return fmt.Sprintf("%s().%s(ctx, &it, data)", caser.String(f.Object.Name), f.GoFieldName)
 	}
-	return fmt.Sprintf("%s().%s(%s)", caser.String(f.Object.Definition.Name), f.GoFieldName, f.CallArgs())
+	return fmt.Sprintf("%s().%s(%s)", caser.String(f.Object.Name), f.GoFieldName, f.CallArgs())
 }
 
 func (f *Field) ArgsFunc() string {
@@ -491,11 +491,11 @@ func (f *Field) ArgsFunc() string {
 		return ""
 	}
 
-	return "field_" + f.Object.Definition.Name + "_" + f.Name + "_args"
+	return "field_" + f.Object.Name + "_" + f.Name + "_args"
 }
 
 func (f *Field) FieldContextFunc() string {
-	return "fieldContext_" + f.Object.Definition.Name + "_" + f.Name
+	return "fieldContext_" + f.Object.Name + "_" + f.Name
 }
 
 func (f *Field) ChildFieldContextFunc(name string) string {
@@ -507,7 +507,7 @@ func (f *Field) ResolverType() string {
 		return ""
 	}
 
-	return fmt.Sprintf("%s().%s(%s)", f.Object.Definition.Name, f.GoFieldName, f.CallArgs())
+	return fmt.Sprintf("%s().%s(%s)", f.Object.Name, f.GoFieldName, f.CallArgs())
 }
 
 func (f *Field) IsInputObject() bool {
diff --git a/codegen/object.go b/codegen/object.go
index 869d1b36..81dce31e 100644
--- a/codegen/object.go
+++ b/codegen/object.go
@@ -147,7 +147,7 @@ func (o *Object) IsConcurrent() bool {
 }
 
 func (o *Object) IsReserved() bool {
-	return strings.HasPrefix(o.Definition.Name, "__")
+	return strings.HasPrefix(o.Name, "__")
 }
 
 func (o *Object) IsMap() bool {
@@ -170,7 +170,7 @@ func (o *Object) HasField(name string) bool {
 
 func (os Objects) ByName(name string) *Object {
 	for i, o := range os {
-		if strings.EqualFold(o.Definition.Name, name) {
+		if strings.EqualFold(o.Name, name) {
 			return os[i]
 		}
 	}
diff --git a/codegen/util.go b/codegen/util.go
index 8a60cd19..f3b2d5f9 100644
--- a/codegen/util.go
+++ b/codegen/util.go
@@ -12,6 +12,7 @@ func findGoNamedType(def types.Type) (*types.Named, error) {
 	}
 
 	namedType, ok := def.(*types.Named)
+	//nolint:staticcheck // yes, it is bad to end in newline here
 	if !ok {
 		return nil, fmt.Errorf("expected %s to be a named type, instead found %T\n", def.String(), def)
 	}
diff --git a/graphql/handler/transport/headers.go b/graphql/handler/transport/headers.go
index 98924819..d0b3a0ac 100644
--- a/graphql/handler/transport/headers.go
+++ b/graphql/handler/transport/headers.go
@@ -19,8 +19,10 @@ func determineResponseContentType(explicitHeaders map[string][]string, r *http.R
 	}
 
 	accept := r.Header.Get("Accept")
+	// TODO(steve): Consider adding config option to opt-in to
+	// default "application/graphql-response+json"
 	if accept == "" {
-		return acceptApplicationGraphqlResponseJson
+		return acceptApplicationJson
 	}
 
 	for _, acceptPart := range strings.Split(accept, ",") {
diff --git a/main.go b/main.go
index 02f56343..8cc83faa 100644
--- a/main.go
+++ b/main.go
@@ -66,9 +66,11 @@ func findModuleRoot(dir string) (roots string) {
 
 func initFile(filename, contents string) error {
 	if err := os.MkdirAll(filepath.Dir(filename), 0o755); err != nil {
+		//nolint:staticcheck // yes, it is bad to end in newline here
 		return fmt.Errorf("unable to create directory for file '%s': %w\n", filename, err)
 	}
 	if err := os.WriteFile(filename, []byte(contents), 0o644); err != nil {
+		//nolint:staticcheck // yes, it is bad to end in newline here
 		return fmt.Errorf("unable to write file '%s': %w\n", filename, err)
 	}
 
@@ -110,6 +112,7 @@ var initCmd = &cli.Command{
 		}
 		modRoot := findModuleRoot(cwd)
 		if modRoot == "" {
+			//nolint:staticcheck // yes, it is bad to end in newline here
 			return errors.New("go.mod is missing. Please, do 'go mod init' first\n")
 		}
 
@@ -121,6 +124,7 @@ var initCmd = &cli.Command{
 		}
 		_, err = config.LoadConfigFromDefaultLocations()
 		if err == nil {
+			//nolint:staticcheck // yes, it is bad to end in newline here
 			return errors.New("gqlgen.yml already exists in a parent directory\n")
 		}
 
diff --git a/plugin/federation/federation.go b/plugin/federation/federation.go
index bd60f789..460caffd 100644
--- a/plugin/federation/federation.go
+++ b/plugin/federation/federation.go
@@ -142,9 +142,10 @@ func (f *Federation) InjectSourcesEarly() ([]*ast.Source, error) {
 	input := ``
 
 	// add version-specific changes on key directive, as well as adding the new directives for federation 2
-	if f.version == 1 {
+	switch f.version {
+	case 1:
 		input += federationVersion1Schema
-	} else if f.version == 2 {
+	case 2:
 		input += federationVersion2Schema
 	}
 


Test patch:
diff --git a/_examples/starwars/starwars_test.go b/_examples/starwars/starwars_test.go
index d5a146bd..01c707fc 100644
--- a/_examples/starwars/starwars_test.go
+++ b/_examples/starwars/starwars_test.go
@@ -220,7 +220,7 @@ func TestStarwars(t *testing.T) {
 		  }
 		}`, &resp, client.Var("episode", "INVALID"))
 
-		require.EqualError(t, err, `http 400: {"errors":[{"message":"INVALID is not a valid Episode","path":["variable","episode"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
+		require.EqualError(t, err, `http 422: {"errors":[{"message":"INVALID is not a valid Episode","path":["variable","episode"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
 	})
 
 	t.Run("introspection", func(t *testing.T) {
diff --git a/codegen/config/initialisms_test.go b/codegen/config/initialisms_test.go
index 04e7aaf8..ec16fd51 100644
--- a/codegen/config/initialisms_test.go
+++ b/codegen/config/initialisms_test.go
@@ -19,7 +19,7 @@ func TestGoInitialismsConfig(t *testing.T) {
 	t.Run("empty initialism config doesn't change anything", func(t *testing.T) {
 		tt := GoInitialismsConfig{}
 		result := tt.determineGoInitialisms()
-		assert.Equal(t, len(templates.CommonInitialisms), len(result))
+		assert.Len(t, result, len(templates.CommonInitialisms))
 	})
 	t.Run("initialism config appends if desired", func(t *testing.T) {
 		tt := GoInitialismsConfig{ReplaceDefaults: false, Initialisms: []string{"ASDF"}}
diff --git a/codegen/config/package_test.go b/codegen/config/package_test.go
index 0f497c0b..1f395a53 100644
--- a/codegen/config/package_test.go
+++ b/codegen/config/package_test.go
@@ -46,13 +46,13 @@ func TestPackageConfig(t *testing.T) {
 
 		require.EqualError(t, p.Check(), "filename must be specified")
 
-		require.Equal(t, "", p.Package)
-		require.Equal(t, "", p.ImportPath())
+		require.Empty(t, p.Package)
+		require.Empty(t, p.ImportPath())
 
 		require.Nil(t, p.Pkg())
 
-		require.Equal(t, "", p.Filename)
-		require.Equal(t, "", p.Dir())
+		require.Empty(t, p.Filename)
+		require.Empty(t, p.Dir())
 	})
 
 	t.Run("when given invalid filename", func(t *testing.T) {
diff --git a/codegen/config/resolver_test.go b/codegen/config/resolver_test.go
index 89c3c84a..c0963386 100644
--- a/codegen/config/resolver_test.go
+++ b/codegen/config/resolver_test.go
@@ -49,13 +49,13 @@ func TestResolverConfig(t *testing.T) {
 
 			require.EqualError(t, p.Check(), "filename must be specified with layout=single-file")
 
-			require.Equal(t, "", p.Package)
-			require.Equal(t, "", p.ImportPath())
+			require.Empty(t, p.Package)
+			require.Empty(t, p.ImportPath())
 
 			require.Nil(t, p.Pkg())
 
-			require.Equal(t, "", p.Filename)
-			require.Equal(t, "", p.Dir())
+			require.Empty(t, p.Filename)
+			require.Empty(t, p.Dir())
 		})
 
 		t.Run("when given invalid filename", func(t *testing.T) {
@@ -131,13 +131,13 @@ func TestResolverConfig(t *testing.T) {
 
 			require.EqualError(t, p.Check(), "dirname must be specified with layout=follow-schema")
 
-			require.Equal(t, "", p.Package)
-			require.Equal(t, "", p.ImportPath())
+			require.Empty(t, p.Package)
+			require.Empty(t, p.ImportPath())
 
 			require.Nil(t, p.Pkg())
 
-			require.Equal(t, "", p.Filename)
-			require.Equal(t, "", p.Dir())
+			require.Empty(t, p.Filename)
+			require.Empty(t, p.Dir())
 		})
 	})
 
diff --git a/codegen/templates/templates_test.go b/codegen/templates/templates_test.go
index 32aabe92..1892dc68 100644
--- a/codegen/templates/templates_test.go
+++ b/codegen/templates/templates_test.go
@@ -39,7 +39,7 @@ func TestToGo(t *testing.T) {
 	require.Equal(t, "A", ToGo("A"))
 	require.Equal(t, "ID", ToGo("ID"))
 	require.Equal(t, "ID", ToGo("id"))
-	require.Equal(t, "", ToGo(""))
+	require.Empty(t, ToGo(""))
 
 	require.Equal(t, "RelatedUrls", ToGo("RelatedUrls"))
 	require.Equal(t, "ITicket", ToGo("ITicket"))
@@ -83,7 +83,7 @@ func TestToGoPrivate(t *testing.T) {
 	require.Equal(t, "a", ToGoPrivate("A"))
 	require.Equal(t, "id", ToGoPrivate("ID"))
 	require.Equal(t, "id", ToGoPrivate("id"))
-	require.Equal(t, "", ToGoPrivate(""))
+	require.Empty(t, ToGoPrivate(""))
 	require.Equal(t, "_", ToGoPrivate("_"))
 
 	require.Equal(t, "idle", ToGoPrivate("IDLE"))
diff --git a/codegen/testserver/followschema/enums_test.go b/codegen/testserver/followschema/enums_test.go
index 37588af3..da1d60ee 100644
--- a/codegen/testserver/followschema/enums_test.go
+++ b/codegen/testserver/followschema/enums_test.go
@@ -40,7 +40,7 @@ func TestEnumsResolver(t *testing.T) {
 			enumInInput(input: {enum: INVALID})
 		}
 		`, &resp)
-		require.EqualError(t, err, `http 400: {"errors":[{"message":"Value \"INVALID\" does not exist in \"EnumTest!\" enum.","locations":[{"line":2,"column":30}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
+		require.EqualError(t, err, `http 422: {"errors":[{"message":"Value \"INVALID\" does not exist in \"EnumTest!\" enum.","locations":[{"line":2,"column":30}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
 	})
 
 	t.Run("input with invalid enum value via vars", func(t *testing.T) {
@@ -51,6 +51,6 @@ func TestEnumsResolver(t *testing.T) {
 			enumInInput(input: $input)
 		}
 		`, &resp, client.Var("input", map[string]any{"enum": "INVALID"}))
-		require.EqualError(t, err, `http 400: {"errors":[{"message":"INVALID is not a valid EnumTest","path":["variable","input","enum"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
+		require.EqualError(t, err, `http 422: {"errors":[{"message":"INVALID is not a valid EnumTest","path":["variable","input","enum"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
 	})
 }
diff --git a/codegen/testserver/followschema/input_test.go b/codegen/testserver/followschema/input_test.go
index e8015595..01b6d6ec 100644
--- a/codegen/testserver/followschema/input_test.go
+++ b/codegen/testserver/followschema/input_test.go
@@ -30,7 +30,7 @@ func TestInput(t *testing.T) {
 
 		err := c.Post(`query { inputSlice(arg: ["ok", 1, 2, "ok"]) }`, &resp)
 
-		require.EqualError(t, err, `http 400: {"errors":[{"message":"String cannot represent a non string value: 1","locations":[{"line":1,"column":32}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"String cannot represent a non string value: 2","locations":[{"line":1,"column":35}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
+		require.EqualError(t, err, `http 422: {"errors":[{"message":"String cannot represent a non string value: 1","locations":[{"line":1,"column":32}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"String cannot represent a non string value: 2","locations":[{"line":1,"column":35}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
 		require.Nil(t, resp.DirectiveArg)
 	})
 
diff --git a/codegen/testserver/singlefile/enums_test.go b/codegen/testserver/singlefile/enums_test.go
index ad63719e..031bfb31 100644
--- a/codegen/testserver/singlefile/enums_test.go
+++ b/codegen/testserver/singlefile/enums_test.go
@@ -40,7 +40,7 @@ func TestEnumsResolver(t *testing.T) {
 			enumInInput(input: {enum: INVALID})
 		}
 		`, &resp)
-		require.EqualError(t, err, `http 400: {"errors":[{"message":"Value \"INVALID\" does not exist in \"EnumTest!\" enum.","locations":[{"line":2,"column":30}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
+		require.EqualError(t, err, `http 422: {"errors":[{"message":"Value \"INVALID\" does not exist in \"EnumTest!\" enum.","locations":[{"line":2,"column":30}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
 	})
 
 	t.Run("input with invalid enum value via vars", func(t *testing.T) {
@@ -51,6 +51,6 @@ func TestEnumsResolver(t *testing.T) {
 			enumInInput(input: $input)
 		}
 		`, &resp, client.Var("input", map[string]any{"enum": "INVALID"}))
-		require.EqualError(t, err, `http 400: {"errors":[{"message":"INVALID is not a valid EnumTest","path":["variable","input","enum"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
+		require.EqualError(t, err, `http 422: {"errors":[{"message":"INVALID is not a valid EnumTest","path":["variable","input","enum"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
 	})
 }
diff --git a/codegen/testserver/singlefile/input_test.go b/codegen/testserver/singlefile/input_test.go
index 319df394..76595275 100644
--- a/codegen/testserver/singlefile/input_test.go
+++ b/codegen/testserver/singlefile/input_test.go
@@ -30,7 +30,7 @@ func TestInput(t *testing.T) {
 
 		err := c.Post(`query { inputSlice(arg: ["ok", 1, 2, "ok"]) }`, &resp)
 
-		require.EqualError(t, err, `http 400: {"errors":[{"message":"String cannot represent a non string value: 1","locations":[{"line":1,"column":32}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"String cannot represent a non string value: 2","locations":[{"line":1,"column":35}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
+		require.EqualError(t, err, `http 422: {"errors":[{"message":"String cannot represent a non string value: 1","locations":[{"line":1,"column":32}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}},{"message":"String cannot represent a non string value: 2","locations":[{"line":1,"column":35}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`)
 		require.Nil(t, resp.DirectiveArg)
 	})
 
diff --git a/graphql/executor/executor_test.go b/graphql/executor/executor_test.go
index 7d7728f2..c5f86fc9 100644
--- a/graphql/executor/executor_test.go
+++ b/graphql/executor/executor_test.go
@@ -26,14 +26,14 @@ func TestExecutor(t *testing.T) {
 	t.Run("validates operation", func(t *testing.T) {
 		t.Run("no operation", func(t *testing.T) {
 			resp := query(exec, "", "")
-			assert.Equal(t, "", string(resp.Data))
+			assert.Empty(t, string(resp.Data))
 			assert.Len(t, resp.Errors, 1)
 			assert.Equal(t, errcode.ValidationFailed, resp.Errors[0].Extensions["code"])
 		})
 
 		t.Run("bad operation", func(t *testing.T) {
 			resp := query(exec, "badOp", "query test { name }")
-			assert.Equal(t, "", string(resp.Data))
+			assert.Empty(t, string(resp.Data))
 			assert.Len(t, resp.Errors, 1)
 			assert.Equal(t, errcode.ValidationFailed, resp.Errors[0].Extensions["code"])
 		})
@@ -133,7 +133,7 @@ func TestExecutor(t *testing.T) {
 		})
 
 		resp := query(exec, "", "invalid")
-		assert.Equal(t, "", string(resp.Data))
+		assert.Empty(t, string(resp.Data))
 		assert.Len(t, resp.Errors, 1)
 		assert.Len(t, errors1, 1)
 		assert.Len(t, errors2, 1)
@@ -173,20 +173,20 @@ func TestExecutorDisableSuggestion(t *testing.T) {
 	exec := testexecutor.New()
 	t.Run("by default, the error message will include suggestions", func(t *testing.T) {
 		resp := query(exec, "", "{nam}")
-		assert.Equal(t, "", string(resp.Data))
+		assert.Empty(t, string(resp.Data))
 		assert.Equal(t, "input:1: Cannot query field \"nam\" on type \"Query\". Did you mean \"name\"?\n", resp.Errors.Error())
 	})
 
 	t.Run("disable suggestion, the error message will not include suggestions", func(t *testing.T) {
 		exec.SetDisableSuggestion(true)
 		resp := query(exec, "", "{nam}")
-		assert.Equal(t, "", string(resp.Data))
+		assert.Empty(t, string(resp.Data))
 		assert.Len(t, resp.Errors, 1)
 		assert.Equal(t, "input:1: Cannot query field \"nam\" on type \"Query\".\n", resp.Errors.Error())
 
 		// check if the error message is displayed correctly even if an error occurs multiple times
 		resp = query(exec, "", "{nam}")
-		assert.Equal(t, "", string(resp.Data))
+		assert.Empty(t, string(resp.Data))
 		assert.Len(t, resp.Errors, 1)
 		assert.Equal(t, "input:1: Cannot query field \"nam\" on type \"Query\".\n", resp.Errors.Error())
 	})
diff --git a/graphql/handler/apollofederatedtracingv1/tracing_test.go b/graphql/handler/apollofederatedtracingv1/tracing_test.go
index 2988e2ca..f4616bb2 100644
--- a/graphql/handler/apollofederatedtracingv1/tracing_test.go
+++ b/graphql/handler/apollofederatedtracingv1/tracing_test.go
@@ -127,7 +127,7 @@ func TestApolloTracing_withMissingOp(t *testing.T) {
 	h.Use(&apollofederatedtracingv1.Tracer{})
 
 	resp := doRequest(h, http.MethodPost, "/graphql", `{}`)
-	assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
+	assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
 	b := resp.Body.Bytes()
 	t.Log(string(b))
 	var respData struct {
diff --git a/graphql/handler/server_test.go b/graphql/handler/server_test.go
index b6d84493..ed24072d 100644
--- a/graphql/handler/server_test.go
+++ b/graphql/handler/server_test.go
@@ -106,7 +106,7 @@ func TestServer(t *testing.T) {
 		})
 
 		resp := get(srv, "/foo?query=invalid")
-		assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
+		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
 		assert.Len(t, errors1, 1)
 		assert.Len(t, errors2, 1)
 	})
diff --git a/graphql/handler/transport/headers_test.go b/graphql/handler/transport/headers_test.go
index 8ecac753..693a2573 100644
--- a/graphql/handler/transport/headers_test.go
+++ b/graphql/handler/transport/headers_test.go
@@ -25,7 +25,7 @@ func TestHeadersWithPOST(t *testing.T) {
 		resp := doRequest(h, "POST", "/graphql", `{"query":"{ name }"}`, "", "application/json")
 		assert.Equal(t, http.StatusOK, resp.Code)
 		assert.Len(t, resp.Header(), 1)
-		assert.Equal(t, "application/graphql-response+json", resp.Header().Get("Content-Type"))
+		assert.Equal(t, "application/json", resp.Header().Get("Content-Type"))
 	})
 
 	t.Run("Headers set", func(t *testing.T) {
@@ -54,7 +54,7 @@ func TestHeadersWithGET(t *testing.T) {
 		resp := doRequest(h, "GET", "/graphql?query={name}", "", "", "application/json")
 		assert.Equal(t, http.StatusOK, resp.Code)
 		assert.Len(t, resp.Header(), 1)
-		assert.Equal(t, "application/graphql-response+json", resp.Header().Get("Content-Type"))
+		assert.Equal(t, "application/json", resp.Header().Get("Content-Type"))
 	})
 
 	t.Run("Headers set", func(t *testing.T) {
diff --git a/graphql/handler/transport/http_get_test.go b/graphql/handler/transport/http_get_test.go
index 03afa6a5..34057879 100644
--- a/graphql/handler/transport/http_get_test.go
+++ b/graphql/handler/transport/http_get_test.go
@@ -56,8 +56,8 @@ func TestGET(t *testing.T) {
 
 	t.Run("invalid variable", func(t *testing.T) {
 		resp := doRequest(h, "GET", `/graphql?query=query($id:Int!){find(id:$id)}&variables={"id":false}`, "", "", "application/json")
-		assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
-		assert.Equal(t, "application/graphql-response+json", resp.Header().Get("Content-Type"))
+		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
+		assert.Equal(t, "application/json", resp.Header().Get("Content-Type"))
 		assert.JSONEq(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, resp.Body.String())
 	})
 
@@ -70,8 +70,8 @@ func TestGET(t *testing.T) {
 
 	t.Run("parse failure", func(t *testing.T) {
 		resp := doRequest(h, "GET", "/graphql?query=!", "", "", "application/json")
-		assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
-		assert.Equal(t, "application/graphql-response+json", resp.Header().Get("Content-Type"))
+		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
+		assert.Equal(t, "application/json", resp.Header().Get("Content-Type"))
 		assert.JSONEq(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}],"data":null}`, resp.Body.String())
 	})
 
diff --git a/graphql/handler/transport/http_post_test.go b/graphql/handler/transport/http_post_test.go
index e34c6393..974f6caf 100644
--- a/graphql/handler/transport/http_post_test.go
+++ b/graphql/handler/transport/http_post_test.go
@@ -61,8 +61,8 @@ func TestPOST(t *testing.T) {
 
 	t.Run("parse failure", func(t *testing.T) {
 		resp := doRequest(h, "POST", "/graphql", `{"query": "!"}`, "", "application/json")
-		assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
-		assert.Equal(t, "application/graphql-response+json", resp.Header().Get("Content-Type"))
+		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
+		assert.Equal(t, "application/json", resp.Header().Get("Content-Type"))
 		assert.JSONEq(t, `{"errors":[{"message":"Unexpected !","locations":[{"line":1,"column":1}],"extensions":{"code":"GRAPHQL_PARSE_FAILED"}}],"data":null}`, resp.Body.String())
 	})
 
@@ -75,8 +75,8 @@ func TestPOST(t *testing.T) {
 
 	t.Run("validation failure", func(t *testing.T) {
 		resp := doRequest(h, "POST", "/graphql", `{"query": "{ title }"}`, "", "application/json")
-		assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
-		assert.Equal(t, "application/graphql-response+json", resp.Header().Get("Content-Type"))
+		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
+		assert.Equal(t, "application/json", resp.Header().Get("Content-Type"))
 		assert.JSONEq(t, `{"errors":[{"message":"Cannot query field \"title\" on type \"Query\".","locations":[{"line":1,"column":3}],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, resp.Body.String())
 	})
 
@@ -89,8 +89,8 @@ func TestPOST(t *testing.T) {
 
 	t.Run("invalid variable", func(t *testing.T) {
 		resp := doRequest(h, "POST", "/graphql", `{"query": "query($id:Int!){find(id:$id)}","variables":{"id":false}}`, "", "application/json")
-		assert.Equal(t, http.StatusBadRequest, resp.Code, resp.Body.String())
-		assert.Equal(t, "application/graphql-response+json", resp.Header().Get("Content-Type"))
+		assert.Equal(t, http.StatusUnprocessableEntity, resp.Code, resp.Body.String())
+		assert.Equal(t, "application/json", resp.Header().Get("Content-Type"))
 		assert.JSONEq(t, `{"errors":[{"message":"cannot use bool as Int","path":["variable","id"],"extensions":{"code":"GRAPHQL_VALIDATION_FAILED"}}],"data":null}`, resp.Body.String())
 	})
 
@@ -104,7 +104,7 @@ func TestPOST(t *testing.T) {
 	t.Run("execution failure", func(t *testing.T) {
 		resp := doRequest(h, "POST", "/graphql", `{"query": "mutation { name }"}`, "", "application/json")
 		assert.Equal(t, http.StatusOK, resp.Code, resp.Body.String())
-		assert.Equal(t, "application/graphql-response+json", resp.Header().Get("Content-Type"))
+		assert.Equal(t, "application/json", resp.Header().Get("Content-Type"))
 		assert.JSONEq(t, `{"errors":[{"message":"mutations are not supported"}],"data":null}`, resp.Body.String())
 	})
 
diff --git a/graphql/playground/helper_test.go b/graphql/playground/helper_test.go
index c4872350..47dbace0 100644
--- a/graphql/playground/helper_test.go
+++ b/graphql/playground/helper_test.go
@@ -46,9 +46,10 @@ func assertNodesIntegrity(t *testing.T, baseUrl string, doc *goquery.Document, s
 		var url string
 		var integrity string
 		for _, attribute := range node.Attr {
-			if attribute.Key == urlAttrKey {
+			switch attribute.Key {
+			case urlAttrKey:
 				url = attribute.Val
-			} else if attribute.Key == integrityAttrKey {
+			case integrityAttrKey:
 				integrity = attribute.Val
 			}
 		}
diff --git a/graphql/string_test.go b/graphql/string_test.go
index 5ca1c36a..9f6424f3 100644
--- a/graphql/string_test.go
+++ b/graphql/string_test.go
@@ -30,7 +30,7 @@ func TestString(t *testing.T) {
 		assert.Equal(t, "123", mustUnmarshalString(t, json.Number("123")))
 		assert.Equal(t, "true", mustUnmarshalString(t, true))
 		assert.Equal(t, "false", mustUnmarshalString(t, false))
-		assert.Equal(t, "", mustUnmarshalString(t, nil))
+		assert.Empty(t, mustUnmarshalString(t, nil))
 	})
 }
 
diff --git a/internal/code/imports_test.go b/internal/code/imports_test.go
index f8ab888c..c5ad0bfd 100644
--- a/internal/code/imports_test.go
+++ b/internal/code/imports_test.go
@@ -37,12 +37,12 @@ func TestImportPathForDir(t *testing.T) {
 	assert.Equal(t, "github.com/99designs/gqlgen/dos", ImportPathForDir(filepath.Join(wd, "..", "..", "dos")))
 
 	// out of module
-	assert.Equal(t, "", ImportPathForDir(filepath.Join(wd, "..", "..", "..")))
+	assert.Empty(t, ImportPathForDir(filepath.Join(wd, "..", "..", "..")))
 
 	if runtime.GOOS == "windows" {
-		assert.Equal(t, "", ImportPathForDir("C:/doesnotexist"))
+		assert.Empty(t, ImportPathForDir("C:/doesnotexist"))
 	} else {
-		assert.Equal(t, "", ImportPathForDir("/doesnotexist"))
+		assert.Empty(t, ImportPathForDir("/doesnotexist"))
 	}
 }
 
diff --git a/plugin/federation/federation_entityresolver_test.go b/plugin/federation/federation_entityresolver_test.go
index 7c8bf949..f222baa3 100644
--- a/plugin/federation/federation_entityresolver_test.go
+++ b/plugin/federation/federation_entityresolver_test.go
@@ -104,9 +104,9 @@ func TestEntityResolver(t *testing.T) {
 		require.Len(t, resp.Entities, 5)
 		require.Equal(t, "first name - 1", resp.Entities[0].Name)
 		require.Equal(t, "first name - 2", resp.Entities[1].Name)
-		require.Equal(t, "", resp.Entities[2].Name)
+		require.Empty(t, resp.Entities[2].Name)
 		require.Equal(t, "first name - 3", resp.Entities[3].Name)
-		require.Equal(t, "", resp.Entities[4].Name)
+		require.Empty(t, resp.Entities[4].Name)
 	})
 
 	t.Run("World entities with nested key", func(t *testing.T) {