Skip to content

enhance: improve helpers to create GraphQLError easier#650

Merged
kamilkisiela merged 5 commits intomainfrom
graphql_error
Jan 14, 2026
Merged

enhance: improve helpers to create GraphQLError easier#650
kamilkisiela merged 5 commits intomainfrom
graphql_error

Conversation

@ardatan
Copy link
Member

@ardatan ardatan commented Jan 12, 2026

Extracted from #628

Introduces pub fn from_message_and_code to create an error with an error code in the extensions which reduce the code a lot in different places.
Helpers that take &str or String are replaced with Into<String> so that extra .to_string() or .into() calls for different variations of string can be avoided.

Benefits;

  • No need for .to_string(), .clone() and .into() for different variations of string
let message_ref: &str = ...;
let code_ref: &str = ...;

let error_from_refs = GraphQLError::from_message_and_code(
- message_ref.to_string()
+ message_ref
- code_ref.to_string()
+ code_ref
);
  • No need to call GraphQLErrorExtensions::from_code thanks to message_and_code helper
- GraphQLError::from_message_and_extensions(
+ GraphQLError::from_message_and_code(
  message,
- GraphQLErrorExtensions::from_code(code
+ code
)

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @ardatan, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request enhances the GraphQLError utility by providing more convenient and flexible methods for error construction. The primary goal is to simplify the process of creating GraphQL errors with specific codes and extensions, thereby improving code readability and reducing redundancy in error handling logic throughout the application.

Highlights

  • New GraphQLError Helper: Introduced a new GraphQLError::from_message_and_code helper function to simplify the creation of GraphQL errors with associated error codes in extensions.
  • Improved String Handling: Refactored existing GraphQLError helper methods (add_subgraph_name, add_affected_path, GraphQLErrorExtensions::new_from_code, GraphQLErrorExtensions::new_from_code_and_service_name) to accept Into<String> for their string arguments, reducing the need for explicit .to_string() or .into() calls.
  • Boilerplate Reduction: Migrated various error handling implementations across the codebase to utilize the new and improved GraphQLError helper functions, significantly reducing boilerplate code.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request is a nice enhancement that improves the ergonomics of creating GraphQLError instances. By introducing from_message_and_code and making other helpers generic over Into<String>, you've reduced boilerplate and increased flexibility across the codebase. The changes significantly improve readability and maintainability.

I've found one area in lib/executor/src/execution/error.rs where the new implementation introduces a minor performance regression by unnecessarily cloning strings. I've provided a suggestion to resolve this while retaining the benefits of the new builder pattern, in line with the repository's performance-first style guide.

@github-actions
Copy link

github-actions bot commented Jan 12, 2026

k6-benchmark results

     ✓ response code was 200
     ✓ no graphql errors
     ✓ valid response structure

     █ setup

     checks.........................: 100.00% ✓ 233784      ✗ 0    
     data_received..................: 6.8 GB  227 MB/s
     data_sent......................: 91 MB   3.0 MB/s
     http_req_blocked...............: avg=3.34µs   min=601ns   med=1.67µs  max=5.48ms   p(90)=2.33µs  p(95)=2.69µs  
     http_req_connecting............: avg=677ns    min=0s      med=0s      max=2.22ms   p(90)=0s      p(95)=0s      
     http_req_duration..............: avg=18.79ms  min=1.93ms  med=17.76ms max=196.65ms p(90)=26ms    p(95)=29.18ms 
       { expected_response:true }...: avg=18.79ms  min=1.93ms  med=17.76ms max=196.65ms p(90)=26ms    p(95)=29.18ms 
     http_req_failed................: 0.00%   ✓ 0           ✗ 77948
     http_req_receiving.............: avg=148.38µs min=23.89µs med=39.75µs max=112.02ms p(90)=94.39µs p(95)=399.74µs
     http_req_sending...............: avg=25.69µs  min=5.71µs  med=10.64µs max=24.3ms   p(90)=16.02µs p(95)=29.04µs 
     http_req_tls_handshaking.......: avg=0s       min=0s      med=0s      max=0s       p(90)=0s      p(95)=0s      
     http_req_waiting...............: avg=18.62ms  min=1.87ms  med=17.62ms max=109.19ms p(90)=25.7ms  p(95)=28.85ms 
     http_reqs......................: 77948   2592.959431/s
     iteration_duration.............: avg=19.24ms  min=5.26ms  med=18.1ms  max=255.55ms p(90)=26.43ms p(95)=29.69ms 
     iterations.....................: 77928   2592.294126/s
     vus............................: 50      min=50        max=50 
     vus_max........................: 50      min=50        max=50 

@github-actions
Copy link

github-actions bot commented Jan 12, 2026

🐋 This PR was built and pushed to the following Docker images:

Image Names: ghcr.io/graphql-hive/router

Platforms: linux/amd64,linux/arm64

Image Tags: ghcr.io/graphql-hive/router:pr-650 ghcr.io/graphql-hive/router:sha-fc32bd4

Docker metadata
{
"buildx.build.ref": "builder-eca4b233-8934-406b-aa91-68ed6b953b21/builder-eca4b233-8934-406b-aa91-68ed6b953b210/h3x6z08eiwb72axphtw5w3teq",
"containerimage.descriptor": {
  "mediaType": "application/vnd.oci.image.index.v1+json",
  "digest": "sha256:be7407147a822e440c4ffbc4aec7135231ee7f8a9494745a553c80e46b0fb287",
  "size": 1609
},
"containerimage.digest": "sha256:be7407147a822e440c4ffbc4aec7135231ee7f8a9494745a553c80e46b0fb287",
"image.name": "ghcr.io/graphql-hive/router:pr-650,ghcr.io/graphql-hive/router:sha-fc32bd4"
}

@ardatan ardatan enabled auto-merge (squash) January 12, 2026 12:53
@kamilkisiela kamilkisiela disabled auto-merge January 13, 2026 09:01
Copy link
Contributor

@kamilkisiela kamilkisiela left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ardatan
Copy link
Member Author

ardatan commented Jan 13, 2026

Merged your PR! Thanks @kamilkisiela !

ardatan and others added 5 commits January 14, 2026 12:11
**Before**

```rust
impl From<PlanExecutionError> for GraphQLError {
    fn from(val: PlanExecutionError) -> Self {
        let mut error = GraphQLError::from_message_and_code(val.to_string(), val.error_code());
        
        if let Some(subgraph_name) = val.subgraph_name() {   // Returns &Option<String>
            error = error.add_subgraph_name(subgraph_name);  // Clones via Into<String>
        }
        
        if let Some(affected_path) = val.affected_path() {   // Returns &Option<String>
            error = error.add_affected_path(affected_path);  // Clones via Into<String>
        }
        error
    }
}
```

What happens:
1. `val.subgraph_name()` returns `&Option<String>`
2. `add_subgraph_name<TStr: Into<String>>()` expects an `Into<String>`
3. When Rust sees `&String` -> `Into<String>`, it uses the impl that
clones the String
4. Same issue for `affected_path`

We end up with 2 unnecessary heap allocations per error conversion.

**After**

I moved owned values out of the structure, to the `add_subgraph_name`
and `add_affected_path` methods.
When Rust sees `Stirng` -> `Into<String>`, it will just use the owned
String, so no clones.
@kamilkisiela kamilkisiela merged commit 3fc4b3d into main Jan 14, 2026
23 checks passed
@kamilkisiela kamilkisiela deleted the graphql_error branch January 14, 2026 11:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants