This guide explains GraphQL validation with detailed visual diagrams showing how our server validates both schemas and queries, with practical examples for both developers and GraphQL newcomers.
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ GRAPHQL VALIDATION LAYERS โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ ๐๏ธ SCHEMA VALIDATION ๐ QUERY VALIDATION โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Purpose: Validate SDL โ โ Purpose: Validate queries โ โ
โ โ When: Schema creation โ โ When: Query execution โ โ
โ โ Checks: Type system โ โ Checks: Syntax & semantics โ โ
โ โ Goal: Ensure schema is โ โ Goal: Ensure query is safe โ โ
โ โ well-formed โ โ and executable โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Examples: Examples: โ
โ โ
Query type exists โ
Valid GraphQL syntax โ
โ โ
All types are defined โ
Fields exist in schema โ
โ โ
Interfaces implemented correctly โ
Arguments match field types โ
โ โ
Unions contain only object types โ
Required fields provided โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
๐ GRAPHQL SDL INPUT
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๐ LEXER & PARSER โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ SDL Text: "type User { id: ID! name: String! }" โ
โ โ Tokenize and Parse โ
โ AST: ObjectTypeDefinition { name: "User", fields: [...] } โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
SCHEMA VALIDATION ENGINE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ ๐ STEP 1: Root Type Validation โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
Query type exists and is Object type โ โ
โ โ โ
Mutation type (if specified) exists and is Objectโ โ
โ โ โ
Subscription type (if specified) exists and Objectโ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ ๐ STEP 2: Type System Validation โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ For each Object Type: โ โ
โ โ โ
All field types are valid output types โ โ
โ โ โ
All argument types are valid input types โ โ
โ โ โ
Interface implementations are correct โ โ
โ โ โ โ
โ โ For each Interface Type: โ โ
โ โ โ
All fields have valid output types โ โ
โ โ โ โ
โ โ For each Union Type: โ โ
โ โ โ
All members are Object types โ โ
โ โ โ
All member types are defined โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ ๐ STEP 3: Type Reference Validation โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
All referenced types are defined โ โ
โ โ โ
No undefined type references โ โ
โ โ โ
Circular references are allowed but tracked โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๐ฆ VALIDATION RESULT โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โ
ValidationResult::Valid โ
โ โโ Schema is ready for query execution! โ
โ โ
โ โ ValidationResult::Invalid(errors) โ
โ โโ List of specific validation errors โ
โ โโ Error locations in SDL โ
โ โโ Human-readable error messages โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Input Schema:
**Input Schema:**
```graphql
type Query {
user(id: ID!): User
posts: [Post!]!
}
type User { id: ID! name: String! posts: [Post!]! profile: UserProfile }
type Post { id: ID! title: String! author: User! tags: [String!] }
type UserProfile { bio: String website: String avatar: String }
**Validation Process:**
```text
๐ VALIDATION STEPS:
1๏ธโฃ ROOT TYPE CHECK:
โ
Query type "Query" exists
โ
Query type is Object type
โ Mutation type not specified (OK)
โ Subscription type not specified (OK)
2๏ธโฃ OBJECT TYPE VALIDATION:
Query:
โ
user field returns User (valid output type)
โ
id argument is ID! (valid input type)
โ
posts field returns [Post!]! (valid output type)
User:
โ
id field is ID! (valid output type)
โ
name field is String! (valid output type)
โ
posts field is [Post!]! (valid output type)
โ
profile field is UserProfile (valid output type)
Post:
โ
All fields have valid output types
โ
author field creates circular reference (User โ Post) - ALLOWED
UserProfile:
โ
All fields have valid output types
3๏ธโฃ TYPE REFERENCE CHECK:
โ
User type is defined
โ
Post type is defined
โ
UserProfile type is defined
โ
All built-in scalars (ID, String) exist
๐ RESULT: ValidationResult::Valid
๐ GRAPHQL QUERY INPUT
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๐ QUERY PARSER โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ Query: "{ user(id: \"123\") { name email } }" โ
โ โ Parse into AST โ
โ Document { operations: [Query { selection_set: [...] }] } โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
QUERY VALIDATION ENGINE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ ๐ STEP 1: Syntax Validation โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
Valid GraphQL syntax โ โ
โ โ โ
Balanced braces and parentheses โ โ
โ โ โ
Proper string escaping โ โ
โ โ โ
Valid field names and arguments โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ ๐ STEP 2: Schema Compliance Validation โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
All fields exist in schema โ โ
โ โ โ
Field arguments match schema definitions โ โ
โ โ โ
Return types are compatible โ โ
โ โ โ
Required arguments are provided โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ ๐ STEP 3: Type System Validation โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
Variables match their declared types โ โ
โ โ โ
Argument values match expected types โ โ
โ โ โ
Fragment spreads are type-compatible โ โ
โ โ โ
Directives are applied correctly โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ ๐ STEP 4: Execution Validation โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
No infinite recursion possible โ โ
โ โ โ
Query complexity within limits โ โ
โ โ โ
Deprecated fields have warnings โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ๐ฆ VALIDATION RESULT โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
ValidationResult::Valid โ Ready for execution โ
โ โ ValidationResult::Invalid(errors) โ Return errors to client โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Schema:
type Query {
user(id: ID!): User
posts(limit: Int = 10): [Post!]!
}
type User {
id: ID!
name: String!
email: String
}
Query Examples:
{
user(id: "123") {
id
name
email
}
}
Validation Steps:
1๏ธโฃ SYNTAX CHECK: โ
Valid GraphQL syntax
2๏ธโฃ FIELD CHECK: โ
user field exists on Query
3๏ธโฃ ARGUMENT CHECK: โ
id argument exists and is ID!
4๏ธโฃ SUB-FIELD CHECK: โ
id, name, email exist on User
5๏ธโฃ TYPE CHECK: โ
All types match
๐ RESULT: ValidationResult::Valid
{
user(id: "123") {
id
fullName # โ Field doesn't exist
posts # โ Field doesn't exist on User
}
nonExistentField # โ Field doesn't exist on Query
}
Validation Steps:
1๏ธโฃ SYNTAX CHECK: โ
Valid GraphQL syntax
2๏ธโฃ FIELD CHECK:
โ
user field exists on Query
โ nonExistentField doesn't exist on Query
3๏ธโฃ SUB-FIELD CHECK:
โ
id exists on User
โ fullName doesn't exist on User
โ posts doesn't exist on User
๐จ RESULT: ValidationResult::Invalid([
"Field 'nonExistentField' doesn't exist on type 'Query'",
"Field 'fullName' doesn't exist on type 'User'",
"Field 'posts' doesn't exist on type 'User'"
])
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ VALIDATION ARCHITECTURE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ SchemaValidator โ โ QueryValidator โ โ
โ โ โ โ โ โ
โ โ validate() โ โ validate() โ โ
โ โ โโ Root types โ โ โโ Syntax โ โ
โ โ โโ Type system โ โ โโ Field exists โ โ
โ โ โโ References โ โ โโ Arguments โ โ
โ โ โโ Consistency โ โ โโ Types match โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โผ โผ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ ValidationResult โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ enum ValidationResult { โ โ
โ โ Valid, โ Ready to proceed โ โ
โ โ Invalid(Vec<GraphQLError>), โ List of specific errors โ โ
โ โ Pending, โ Validation in progress โ โ
โ โ } โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โผ โผ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ Schema Service โ โ Query Executor โ โ
โ โ (Schema ready) โ โ (Execute query) โ โ
โ โโโโโโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Our validation system is built around these key components:
pub struct SchemaValidator;
impl SchemaValidator {
pub fn validate(&self, schema: &Schema) -> ValidationResult {
let mut errors = Vec::new();
// Rule 1: Schema must have a Query type
if schema.get_type(&schema.query_type).is_none() {
errors.push(GraphQLError::validation_error(
format!("Query type '{}' is not defined", schema.query_type)
));
}
// Rule 2: Validate all type definitions
for (name, type_def) in &schema.types {
if let Err(type_errors) = schema.validate_type(name, type_def) {
errors.extend(type_errors);
}
}
if errors.is_empty() {
ValidationResult::Valid
} else {
ValidationResult::Invalid(errors)
}
}
}
pub struct QueryValidator;
impl QueryValidator {
pub fn validate(&self, query: &Query, schema: &Schema) -> ValidationResult {
// Basic validation - comprehensive validation will be added later
if query.is_empty() {
ValidationResult::invalid("Query string cannot be empty".to_string())
} else {
// TODO: Parse and validate query syntax
// TODO: Validate query against schema
ValidationResult::Valid
}
}
}
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ VALIDATION STATUS OVERVIEW โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ โ
SCHEMA VALIDATION (Completed) โ
โ โโ Root type validation (Query, Mutation, Subscription) โ
โ โโ Type system validation (Object, Interface, Union, Enum) โ
โ โโ Type reference validation โ
โ โโ Interface implementation validation โ
โ โโ Union member validation โ
โ โโ Circular reference detection โ
โ โ
โ ๐ง QUERY VALIDATION (Basic Implementation) โ
โ โโ โ
Empty query detection โ
โ โโ โ
Basic syntax validation (via parser) โ
โ โโ ๐ Field existence validation (Planned) โ
โ โโ ๐ Argument validation (Planned) โ
โ โโ ๐ Type compatibility validation (Planned) โ
โ โโ ๐ Fragment validation (Planned) โ
โ โ
โ ๐ ADVANCED VALIDATION (Planned) โ
โ โโ Query complexity analysis โ
โ โโ Depth limiting โ
โ โโ Rate limiting integration โ
โ โโ Custom validation rules โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Our validation system includes comprehensive tests:
#[cfg(test)]
mod validation_tests {
use super::*;
#[test]
fn test_schema_validator_missing_query_type() {
let schema = Schema::new("NonExistentQuery".to_string());
let validator = SchemaValidator::new();
let result = validator.validate(&schema);
assert!(matches!(result, ValidationResult::Invalid(_)));
}
#[test]
fn test_query_validator_empty_query() {
let query = Query::new(String::new());
let schema = Schema::new("Query".to_string());
let validator = QueryValidator::new();
let result = validator.validate(&query, &schema);
assert!(result.is_invalid());
}
#[test]
fn test_valid_schema_validation() {
let mut schema = Schema::new("Query".to_string());
// Add Query type definition...
let validator = SchemaValidator::new();
let result = validator.validate(&schema);
assert!(result.is_valid());
}
}
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ PLANNED VALIDATION FEATURES โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ ๐ฏ COMPREHENSIVE QUERY VALIDATION โ
โ โโ Field-level validation against schema โ
โ โโ Argument type and requirement validation โ
โ โโ Fragment spread validation โ
โ โโ Variable definition and usage validation โ
โ โโ Directive validation โ
โ โ
โ ๐ QUERY COMPLEXITY ANALYSIS โ
โ โโ Query depth analysis โ
โ โโ Field complexity scoring โ
โ โโ Query cost estimation โ
โ โโ Configurable limits โ
โ โ
โ ๐ก๏ธ SECURITY VALIDATION โ
โ โโ Input sanitization โ
โ โโ Query whitelisting โ
โ โโ Rate limiting per field โ
โ โโ Introspection query filtering โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Future versions will support custom validation rules:
pub trait ValidationRule {
fn validate(&self, query: &Query, schema: &Schema) -> Vec<GraphQLError>;
}
pub struct MaxDepthRule {
max_depth: u32,
}
impl ValidationRule for MaxDepthRule {
fn validate(&self, query: &Query, _schema: &Schema) -> Vec<GraphQLError> {
// Implement depth validation logic
vec![]
}
}
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ COMPLETE REQUEST PIPELINE โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ โ
โ 1. HTTP Request โ Parse Query โ
โ โ โ
โ โผ โ
โ 2. Query Parser โ AST โ
โ โ โ
โ โผ โ
โ 3. QueryValidator โ ValidationResult โ
โ โ โ
โ โโ Valid? โ Continue to Step 4 โ
โ โโ Invalid? โ Return errors immediately โ
โ โ
โ 4. Query Executor โ Execute validated query โ
โ โ โ
โ โผ โ
โ 5. Field Resolvers โ Fetch data โ
โ โ โ
โ โผ โ
โ 6. Response Builder โ JSON Response โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Good validation errors are specific and actionable:
{
"errors": [
{
"message": "Field 'fullName' doesn't exist on type 'User'. Did you mean 'name'?",
"locations": [{"line": 3, "column": 5}],
"path": ["user", "fullName"],
"extensions": {
"code": "FIELD_NOT_FOUND",
"typeName": "User",
"fieldName": "fullName",
"availableFields": ["id", "name", "email"]
}
}
]
}
This validation system ensures that only safe, well-formed queries reach the execution engine, providing excellent developer experience while maintaining security and performance.