Troubleshooting
Common issues and solutions when using the GraphQL Code Generator.
Compilation Errors
Generated Code Not Found
Symptoms:
1error: package com.example.generated does not exist2error: cannot find symbol
Causes & Solutions:
- Generated code directory not in source sets
1sourceSets {2main {3java {4srcDir 'build/generated/graphql' // Add this5}6}7}
- Code generation didn't run
1# Run generation manually2./gradlew generateGraphQLCode34# Or regenerate everything5./gradlew clean generateGraphQLCode compileJava
- IDE not recognizing generated sources
IntelliJ IDEA:
- Right-click project → "Reload Gradle Project"
- Or: File → Invalidate Caches → Restart
Eclipse:
- Right-click project → Gradle → Refresh Gradle Project
VS Code:
- Reload window (Cmd/Ctrl + Shift + P → "Reload Window")
Circular Dependency Error
Symptoms:
1Circular dependency between the following tasks:2:compileJava3\--- :generateGraphQL4\--- :compileJava (*)
Cause: The code generator class needs to be compiled before it can run, but it depends on code generation completing.
Solution: Put your generator class in a separate source set:
1sourceSets {2codegen {3java {4srcDir 'src/codegen/java'5}6}7}89tasks.register('generateGraphQLCode', JavaExec) {10// Use codegen classpath, not main11classpath = sourceSets.codegen.runtimeClasspath12mainClass = 'com.example.codegen.MyCodeGenerator'13}
Or use a separate buildSrc module for your generator.
Package Name Mismatch
Symptoms:
1error: class MySchemaContext is public, should be declared in a file named MySchemaContext.java
Cause: The generated package doesn't match the directory structure.
Solution: Ensure your packageName in the generator matches the output directory structure:
1new GraphQLCodeGenerator.Builder()2.generatedSourcesPackageName("com.example.generated") // Must match directory3.generatedSourcesOutputDir("build/generated/graphql")4.build();
The generator creates: build/generated/graphql/com/example/generated/MySchemaContext.java
Runtime Errors
Conversion Boilerplate Everywhere
Symptoms: Every query and mutation method ends with the same hand-written domain-to-model wrapping.
Cause: The schema doesn't map the type to your domain class, so generated signatures use the generated models and you convert at every call site.
Solution: Add a @javaType directive to your schema (or an addTypeMapping builder call). Generated signatures then use your domain class directly, and the schema context declares a single to<Type> converter you implement once:
1type User @javaType(class: "com.example.domain.User") {2id: ID!3name: String!4}
NullPointerException Resolving a Field
Symptoms:
1NullPointerException at MySchemaContextImpl.toUser(MySchemaContextImpl.java:42)
Cause: A query method or converter assumed non-null data.
Solution: Handle null cases—nullable GraphQL fields should resolve to null, not throw:
1@Override2public MyPost post(String id) {3DomainPost domain = postService.findById(id);45// Return null for not found (GraphQL semantics)6if (domain == null) {7return null;8}910return toPost(domain);11}
Schema Errors
Scalar Type Not Found
Symptoms:
1Unknown type 'UUID' in field 'id'
Cause: Custom scalar not registered with the generator.
Solution: Add scalar mapping:
1new GraphQLCodeGenerator.Builder()2.sdlPath("src/main/resources/schema.graphql")3.generatedSourcesPackageName("com.example.generated")4.addCustomScalar("UUID", UuidScalar.class) // Add this5.build();
The scalar must also be declared in the SDL (scalar UUID).
Directive Not Recognized
Symptoms:
1Unknown directive '@javaType'
Cause: The @javaType directive must be defined in your schema.
Solution: Add the directive definition:
1directive @javaType(2class: String!3) on OBJECT | INTERFACE | UNION
Conflicting Type Names
Symptoms:
1error: duplicate class: com.example.generated.Query
Cause: Generated type name conflicts with an existing class.
Solution: Use classNamePrefix:
1new GraphQLCodeGenerator.Builder()2.sdlPath("src/main/resources/schema.graphql")3.generatedSourcesPackageName("com.example.generated")4.classNamePrefix("MyAPI") // Generates MyAPIQuery instead of Query5.build();
Gradle Build Issues
Code Generation Runs Every Build
Symptoms: Build always regenerates code even when schema hasn't changed.
Cause: Missing input/output declarations.
Solution:
1tasks.register('generateGraphQLCode', JavaExec) {2// ...existing configuration...34// Add these for incremental builds5inputs.files(fileTree('src/main/resources/graphql'))6outputs.dir('build/generated/graphql')7}
Out of Memory During Generation
Symptoms:
1java.lang.OutOfMemoryError: Java heap space
Cause: Very large schema or insufficient heap size.
Solution:
1tasks.register('generateGraphQLCode', JavaExec) {2// ...existing configuration...34jvmArgs = ['-Xmx2g'] // Increase heap size5}
Build Cache Not Working
Symptoms: Code regenerates even with identical inputs.
Cause: Task not properly configured for caching.
Solution:
1tasks.register('generateGraphQLCode', JavaExec) {2// ...existing configuration...34// Declare all inputs5inputs.file('src/main/resources/schema.graphql')6inputs.file('src/main/java/com/example/codegen/MyCodeGenerator.java')78// Declare outputs9outputs.dir('build/generated/graphql')10.withPropertyName('outputDir')1112// Enable caching13outputs.cacheIf { true }14}
Implementation Errors
Type Safety Violations
Symptoms:
1warning: [unchecked] unchecked conversion
Cause: Using raw types or incorrect generic types.
Solution: Use proper generic types:
1// Wrong2List posts() {3return domainPosts.stream()4.map(this::toPost)5.collect(Collectors.toList());6}78// Right9List<MyPost> posts() {10return domainPosts.stream()11.map(this::toPost)12.collect(Collectors.toList());13}
Sealed Class Violations
Symptoms: A MySealedClassException is thrown, or you're tempted to implement a generated interface (like a union type) directly.
Cause: Generated models are sealed by design—generated interfaces declare a sealed(...) method that only the generated abstract classes implement, so arbitrary anonymous implementations are rejected.
Solution: Don't implement generated interfaces directly. Extend (or create anonymous instances of) the generated abstract classes instead—e.g. return a MyProduct (which implements MySearchResult) rather than implementing MySearchResult yourself.
Union Type Resolution Fails
Symptoms:
1GraphQLError: Abstract type SearchResult must resolve to an Object type
Cause: A union field returned an object that isn't an instance of any generated member model, so the generated type resolver couldn't identify it.
Solution: Return instances of the generated member classes—resolution is automatic from there:
1@Override2public MySearchResult search(String query) {3Object result = searchService.search(query);45if (result instanceof DomainProduct) {6return toProduct((DomainProduct) result); // a MyProduct7} else if (result instanceof DomainArticle) {8return toArticle((DomainArticle) result); // a MyArticle9} else if (result == null) {10return null;11} else {12throw new IllegalStateException(13"Unexpected search result type: " + result.getClass().getName());14}15}
Performance Issues
Slow Query Resolution
Symptoms: GraphQL queries take a long time to execute.
Causes & Solutions:
- N+1 Query Problem
1// Bad: Loads author for each post separately2@Override3public MyAuthor author() {4return toAuthor(userService.findById(post.getAuthorId()));5}67// Good: Batch load all authors upfront8@Override9public List<MyPost> posts() {10List<DomainPost> domainPosts = postService.findAll();1112// Pre-load all authors in single query13Set<String> authorIds = domainPosts.stream()14.map(DomainPost::getAuthorId)15.collect(Collectors.toSet());1617Map<String, DomainUser> authors = userService.findByIds(authorIds)18.stream()19.collect(Collectors.toMap(DomainUser::getId, u -> u));2021// Return posts with pre-loaded authors22return domainPosts.stream()23.map(post -> toPost(post, authors.get(post.getAuthorId())))24.collect(Collectors.toList());25}
- Unnecessary Field Resolution
Use lazy loading for expensive fields (see Implementation Patterns).
Getting Help
If you're still experiencing issues:
- Check the logs: Enable debug logging for
com.psddev.graphql - Verify schema: Use a GraphQL schema validator
- Compare with examples: See Advanced Examples
- Simplify: Create a minimal reproduction case
- Ask for help: Include your schema, generated code, and error messages
Next Steps
- Implementation Patterns - Learn best practices
- Advanced Examples - See complex scenarios