0.0
The project is in a healthy, maintained state
Maps GraphQL-Ruby runtime fields to Prism source locations and reports resolver contract errors.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
2025
2026
 Dependencies

Runtime

>= 1.0
 Project Readme

graphql-doctor

Catch GraphQL-Ruby resolver contract mismatches before runtime

Gem Version Downloads Build Status Ruby Version License

Features · Installation · Quick Start · Commands · Configuration · CI · Diagnostics


graphql-doctor connects GraphQL-Ruby's runtime schema with Prism-parsed Ruby source. It catches missing resolver methods, incompatible keywords, invalid callback signatures, and unregistered members before a query reaches production.

Features

  • Maps runtime fields and arguments back to exact Ruby source locations
  • Checks resolver method existence and visibility
  • Verifies keywords after loads:, as:, extras:, defaults, and nullability
  • Validates prepare:, ready?, authorized?, and opt-in execution callbacks
  • Finds unregistered resolver and mutation classes
  • Reports as text, JSON, SARIF, or GitHub Actions annotations
  • Supports schema dumps for CI jobs that cannot boot the application
  • Parses in parallel and caches source indexes

Installation

Add the gem to the application that owns the schema:

group :development, :test do
  gem "graphql-doctor"
end

Then install it:

bundle install

Requirements

  • Ruby 3.1+
  • GraphQL-Ruby 2.0+
  • Prism is the only runtime dependency

On Ruby 3.4, use GraphQL-Ruby 2.0.32 or newer. GraphQL-Ruby 2.0.x also needs racc on Ruby 3.4.

Quick Start

Create .graphql-doctor.yml in the application root:

schema: MyAppSchema
require: ./config/environment

Run the contract checks:

bundle exec graphql-doctor check

By default, Ruby files under app/graphql/**/*.rb are indexed and errors cause exit status 1.

Commands

Command Description
graphql-doctor check [paths] Check resolver contracts; this is the default command
graphql-doctor dump-schema Write the reflected runtime schema as JSON
graphql-doctor coverage Show source-to-runtime field mapping coverage
graphql-doctor explain CODE Print the reference for a diagnostic code
graphql-doctor version Print the installed version

Common options:

bundle exec graphql-doctor check app/graphql --format github
bundle exec graphql-doctor check --only GQLD301,GQLD303
bundle exec graphql-doctor check --fail-level warning
bundle exec graphql-doctor check --no-cache --jobs 4
bundle exec graphql-doctor check --format sarif --out tmp/results.sarif

Output formats are text, json, sarif, and github. NO_COLOR and --no-color disable ANSI output.

Exit statuses are 0 when the configured threshold is clear, 1 when diagnostics meet --fail-level, and 2 for configuration, boot, or execution failures.

Configuration

Option Type Default Description
schema String null GraphQL schema constant to inspect
require String ./config/environment File loaded before resolving the schema
include String[] app/graphql/**/*.rb Ruby source paths or glob patterns to index
exclude String[] [] Paths or glob patterns to skip
checks Mapping See below Per-code enabled and severity overrides
allow_underlying_object String[] [] Types allowed to resolve through their backing objects
abstract_classes String[] [] Base resolvers and mutations excluded from registration checks
experimental.new_execution_api Boolean false Enable checks for the experimental execution callback
require_suppression_reason Boolean false Ignore suppression comments without a reason

Example configuration:

schema: MyAppSchema
require: ./config/environment

include:
  - app/graphql/**/*.rb
exclude:
  - app/graphql/legacy/**/*.rb

checks:
  GQLD201: { severity: warning }
  GQLD305: { enabled: true }

allow_underlying_object:
  - Types::UserType
abstract_classes:
  - Mutations::BaseMutation

require_suppression_reason: true

GQLD102, GQLD103, and GQLD305 are disabled by default. Use --only or checks to enable them.

CI

Use GitHub annotations for a single-job check:

bundle exec graphql-doctor check --format github

For split CI, boot the application once and pass the schema dump to the checking job:

bundle exec graphql-doctor dump-schema --out tmp/schema.json
bundle exec graphql-doctor check --no-boot --schema-dump tmp/schema.json

Running check --no-boot without a schema dump performs static checks only. Cache files are stored under .graphql-doctor/cache; add .graphql-doctor/ to the target application's .gitignore.

Diagnostics

See the diagnostic reference for every code, its runtime impact, possible false positives, and fixes.

bundle exec graphql-doctor explain GQLD301

Suppress one line or a whole file when the behavior is intentional:

def resolve(id:) # graphql-doctor:disable GQLD301 -- handled by an extension
# graphql-doctor:disable-file GQLD201 -- objects provide all fields

How It Works

  1. Prism indexes GraphQL DSL calls, Ruby methods, callbacks, and source locations.
  2. GraphQL-Ruby provides the booted runtime schema, or --schema-dump supplies an earlier snapshot.
  3. The correlator joins source definitions to runtime fields and arguments.
  4. Contract checks produce diagnostics without executing application queries.

The runtime schema is the source of truth for GraphQL behavior; Prism is the source of truth for Ruby structure and locations.

Development

bundle install
bundle exec rake test

For the GitHub Pages landing page, see site development and publishing.

Contributing

Bug reports and pull requests are welcome at https://github.com/ydah/graphql-doctor.

License

Released under the MIT License.