Skip to main content

apollo_federation/error/
mod.rs

1pub(crate) mod suggestion;
2
3use std::cmp::Ordering;
4use std::fmt::Display;
5use std::fmt::Formatter;
6use std::fmt::Write;
7use std::ops::Range;
8use std::sync::LazyLock;
9
10use apollo_compiler::InvalidNameError;
11use apollo_compiler::Name;
12use apollo_compiler::ast::OperationType;
13use apollo_compiler::parser::LineColumn;
14use apollo_compiler::validation::DiagnosticList;
15use apollo_compiler::validation::WithErrors;
16
17use crate::subgraph::SubgraphError;
18use crate::subgraph::spec::FederationSpecError;
19use crate::subgraph::typestate::HasMetadata;
20use crate::subgraph::typestate::Subgraph;
21
22/// Create an internal error.
23///
24/// # Example
25/// ```rust
26/// use apollo_federation::internal_error;
27/// use apollo_federation::error::FederationError;
28/// # fn may_be_none() -> Option<()> { None }
29///
30/// const NAME: &str = "the thing";
31/// let result: Result<(), FederationError> = may_be_none()
32///     .ok_or_else(|| internal_error!("Expected {NAME} to be Some"));
33/// ```
34#[macro_export]
35macro_rules! internal_error {
36    ( $( $arg:tt )+ ) => {
37        $crate::error::FederationError::internal(format!( $( $arg )+ ))
38    }
39}
40
41/// Break out of the current function, returning an internal error.
42///
43/// # Example
44/// ```rust
45/// use apollo_federation::bail;
46/// use apollo_federation::error::FederationError;
47/// # fn may_be_none() -> Option<()> { None }
48///
49/// fn example() -> Result<(), FederationError> {
50///     bail!("Something went horribly wrong");
51///     unreachable!()
52/// }
53/// #
54/// # _ = example();
55/// ```
56#[macro_export]
57macro_rules! bail {
58    ( $( $arg:tt )+ ) => {
59        return Err($crate::internal_error!( $( $arg )+ ).into())
60    }
61}
62
63/// A safe assertion: in debug mode, it panicks on failure, and in production, it returns an
64/// internal error.
65///
66/// Treat this as an assertion. It must only be used for conditions that *should never happen*
67/// in normal operation.
68///
69/// # Example
70/// ```rust,no_run
71/// use apollo_federation::ensure;
72/// use apollo_federation::error::FederationError;
73/// # fn may_be_none() -> Option<()> { None }
74///
75/// fn example() -> Result<(), FederationError> {
76///     ensure!(1 == 0, "Something went horribly wrong");
77///     unreachable!()
78/// }
79/// ```
80#[macro_export]
81macro_rules! ensure {
82    ( $expr:expr, $( $arg:tt )+ ) => {
83        #[cfg(debug_assertions)]
84        {
85            if false {
86                return Err($crate::error::FederationError::internal("ensure!() must be used in a function that returns a Result").into());
87            }
88            assert!($expr, $( $arg )+);
89        }
90
91        #[cfg(not(debug_assertions))]
92        if !$expr {
93            $crate::bail!( $( $arg )+ );
94        }
95    }
96}
97
98// What we really needed here was the string representations in enum form, this isn't meant to
99// replace AST components.
100#[derive(Clone, Debug, strum_macros::Display)]
101enum SchemaRootKind {
102    #[strum(to_string = "query")]
103    Query,
104    #[strum(to_string = "mutation")]
105    Mutation,
106    #[strum(to_string = "subscription")]
107    Subscription,
108}
109
110impl From<SchemaRootKind> for String {
111    fn from(value: SchemaRootKind) -> Self {
112        value.to_string()
113    }
114}
115
116#[derive(Clone, Debug, strum_macros::Display, PartialEq, Eq)]
117pub enum UnsupportedFeatureKind {
118    #[strum(to_string = "alias")]
119    Alias,
120}
121
122/// Modeled after `SubgraphLocation` defined in `apollo_composition`, so this struct can be
123/// converted to it.
124#[derive(Clone, Debug)]
125pub struct SubgraphLocation {
126    /// Subgraph name
127    pub subgraph: String, // TODO: Change this to `Arc<str>`, once `Merger` is updated.
128    /// Source code range in the subgraph schema document
129    pub range: Range<LineColumn>,
130}
131
132pub type Locations = Vec<SubgraphLocation>;
133
134/// Supergraph coordinates carried on `@inaccessible` API schema errors so composition can attach
135/// subgraph source locations (port of JS `inaccessible_elements` / `inaccessible_referencers`
136/// extensions and `updateInaccessibleErrorsWithLinkToSubgraphs`). Those locations are surfaced on
137/// [`CompositionError::MergeError`] as [`SubgraphLocation`] entries (Rust equivalent of JS
138/// `withModifiedErrorNodes`).
139#[derive(Clone, Debug, Default)]
140pub struct InaccessibleCompositionLinks {
141    pub elements: Vec<String>,
142    pub referencers: Vec<String>,
143}
144
145pub(crate) trait HasLocations {
146    fn locations<T: HasMetadata>(&self, subgraph: &Subgraph<T>) -> Locations;
147}
148
149impl<HL: HasLocations> HasLocations for &HL {
150    fn locations<T: HasMetadata>(&self, subgraph: &Subgraph<T>) -> Locations {
151        HL::locations(self, subgraph)
152    }
153}
154
155#[derive(Debug, Clone, thiserror::Error)]
156pub enum CompositionError {
157    #[error("[{subgraph}] {error}")]
158    SubgraphError {
159        subgraph: String,
160        error: SingleFederationError,
161        locations: Locations,
162    },
163    #[error("{error}")]
164    MergeError {
165        error: SingleFederationError,
166        locations: Locations,
167    },
168    #[error("{error}")]
169    MergeValidationError { error: SingleFederationError },
170    #[error("{message}")]
171    ContextualArgumentNotContextualInAllSubgraphs {
172        message: String,
173        locations: Locations,
174    },
175    #[error("{message}")]
176    EmptyMergedEnumType {
177        message: String,
178        locations: Locations,
179    },
180    #[error("{message}")]
181    EnumValueMismatch { message: String },
182    #[error("{message}")]
183    ExternalArgumentTypeMismatch { message: String },
184    #[error("{message}")]
185    ExternalTypeMismatch { message: String },
186    #[error("{message}")]
187    ExternalArgumentDefaultMismatch { message: String },
188    #[error("{message}")]
189    InvalidGraphQL { message: String },
190    #[error(transparent)]
191    InvalidGraphQLName(InvalidNameError),
192    #[error(r#"{message} in @fromContext substring "{context}""#)]
193    FromContextParseError { context: String, message: String },
194    #[error(
195        "Unsupported custom directive @{name} on fragment spread. Due to query transformations during planning, the router requires directives on fragment spreads to support both the FRAGMENT_SPREAD and INLINE_FRAGMENT locations."
196    )]
197    UnsupportedSpreadDirective { name: Name },
198    #[error("{message}")]
199    DirectiveDefinitionInvalid { message: String },
200    #[error("{message}")]
201    TypeDefinitionInvalid { message: String },
202    #[error("{message}")]
203    InterfaceObjectUsageError { message: String },
204    #[error("{message}")]
205    InterfaceKeyMissingImplementationType { message: String },
206    #[error("{message}")]
207    TypeKindMismatch { message: String },
208    #[error("{message}")]
209    ShareableHasMismatchedRuntimeTypes { message: String },
210    #[error("{message}")]
211    SatisfiabilityError { message: String },
212    #[error("{message}")]
213    MaxValidationSubgraphPathsExceeded { message: String },
214    #[error("{message}")]
215    InternalError { message: String },
216    #[error("{message}")]
217    ExternalArgumentMissing { message: String },
218    #[error("{message}")]
219    ExternalMissingOnBase { message: String },
220    #[error("{message}")]
221    MergedDirectiveApplicationOnExternal { message: String },
222    #[error("{message}")]
223    LinkImportNameMismatch { message: String },
224    #[error("{message}")]
225    InvalidFieldSharing {
226        message: String,
227        locations: Locations,
228    },
229    #[error(
230        "[{subgraph}] Type \"{dest}\" is an extension type, but there is no type definition for \"{dest}\" in any subgraph."
231    )]
232    ExtensionWithNoBase {
233        subgraph: String,
234        dest: String,
235        locations: Locations,
236    },
237    #[error("{message}")]
238    DirectiveCompositionError { message: String },
239    #[error("{message}")]
240    InconsistentInputObjectField { message: String },
241    #[error("{message}")]
242    RequiredArgumentMissingInSomeSubgraph {
243        message: String,
244        locations: Locations,
245    },
246    #[error("{message}")]
247    RequiredInputFieldMissingInSomeSubgraph {
248        message: String,
249        locations: Locations,
250    },
251    #[error("{message}")]
252    EmptyMergedInputType {
253        message: String,
254        locations: Locations,
255    },
256    #[error("{message}")]
257    InputFieldMergeFailed {
258        message: String,
259        locations: Locations,
260    },
261    #[error("{message}")]
262    FieldArgumentTypeMismatch { message: String },
263    #[error("{message}")]
264    FieldTypeMismatch { message: String },
265    #[error("{message}")]
266    OverrideCollisionWithAnotherDirective { message: String },
267    #[error("{message}")]
268    OverrideFromSelfError { message: String },
269    #[error("{message}")]
270    OverrideLabelInvalid { message: String },
271    #[error("{message}")]
272    OverrideOnInterface { message: String },
273    #[error("{message}")]
274    OverrideSourceHasOverride { message: String },
275    #[error("{message}")]
276    QueryRootMissing { message: String },
277    #[error("{message}")]
278    ArgumentDefaultMismatch {
279        message: String,
280        locations: Locations,
281    },
282    #[error("{message}")]
283    InputFieldDefaultMismatch {
284        message: String,
285        locations: Locations,
286    },
287    #[error("{message}")]
288    InterfaceFieldNoImplem {
289        message: String,
290        locations: Locations,
291    },
292}
293
294impl CompositionError {
295    pub fn code(&self) -> ErrorCode {
296        match self {
297            Self::SubgraphError { error, .. } => error.code(),
298            Self::MergeError { error, .. } => error.code(),
299            Self::MergeValidationError { error, .. } => error.code(),
300            Self::ContextualArgumentNotContextualInAllSubgraphs { .. } => {
301                ErrorCode::ContextualArgumentNotContextualInAllSubgraphs
302            }
303            Self::EmptyMergedEnumType { .. } => ErrorCode::EmptyMergedEnumType,
304            Self::EnumValueMismatch { .. } => ErrorCode::EnumValueMismatch,
305            Self::ExternalTypeMismatch { .. } => ErrorCode::ExternalTypeMismatch,
306            Self::ExternalArgumentTypeMismatch { .. } => ErrorCode::ExternalArgumentTypeMismatch,
307            Self::ExternalArgumentDefaultMismatch { .. } => {
308                ErrorCode::ExternalArgumentDefaultMismatch
309            }
310            Self::InvalidGraphQL { .. } => ErrorCode::InvalidGraphQL,
311            Self::InvalidGraphQLName(..) => ErrorCode::InvalidGraphQL,
312            Self::FromContextParseError { .. } => ErrorCode::InvalidGraphQL,
313            Self::UnsupportedSpreadDirective { .. } => ErrorCode::InvalidGraphQL,
314            Self::DirectiveDefinitionInvalid { .. } => ErrorCode::DirectiveDefinitionInvalid,
315            Self::TypeDefinitionInvalid { .. } => ErrorCode::TypeDefinitionInvalid,
316            Self::InterfaceObjectUsageError { .. } => ErrorCode::InterfaceObjectUsageError,
317            Self::InterfaceKeyMissingImplementationType { .. } => {
318                ErrorCode::InterfaceKeyMissingImplementationType
319            }
320            Self::TypeKindMismatch { .. } => ErrorCode::TypeKindMismatch,
321            Self::ShareableHasMismatchedRuntimeTypes { .. } => {
322                ErrorCode::ShareableHasMismatchedRuntimeTypes
323            }
324            Self::SatisfiabilityError { .. } => ErrorCode::SatisfiabilityError,
325            Self::MaxValidationSubgraphPathsExceeded { .. } => {
326                ErrorCode::MaxValidationSubgraphPathsExceeded
327            }
328            Self::InternalError { .. } => ErrorCode::Internal,
329            Self::ExternalArgumentMissing { .. } => ErrorCode::ExternalArgumentMissing,
330            Self::ExternalMissingOnBase { .. } => ErrorCode::ExternalMissingOnBase,
331            Self::MergedDirectiveApplicationOnExternal { .. } => {
332                ErrorCode::MergedDirectiveApplicationOnExternal
333            }
334            Self::LinkImportNameMismatch { .. } => ErrorCode::LinkImportNameMismatch,
335            Self::InvalidFieldSharing { .. } => ErrorCode::InvalidFieldSharing,
336            Self::InconsistentInputObjectField { .. } => ErrorCode::Internal, // This is for hints, not errors
337            Self::RequiredArgumentMissingInSomeSubgraph { .. } => {
338                ErrorCode::RequiredArgumentMissingInSomeSubgraph
339            }
340            Self::RequiredInputFieldMissingInSomeSubgraph { .. } => {
341                ErrorCode::RequiredInputFieldMissingInSomeSubgraph
342            }
343            Self::EmptyMergedInputType { .. } => ErrorCode::EmptyMergedInputType,
344            Self::InputFieldMergeFailed { .. } => ErrorCode::InputFieldMergeFailed,
345            Self::ExtensionWithNoBase { .. } => ErrorCode::ExtensionWithNoBase,
346            Self::DirectiveCompositionError { .. } => ErrorCode::DirectiveCompositionError,
347            Self::FieldArgumentTypeMismatch { .. } => ErrorCode::FieldArgumentTypeMismatch,
348            Self::FieldTypeMismatch { .. } => ErrorCode::FieldTypeMismatch,
349            Self::OverrideCollisionWithAnotherDirective { .. } => {
350                ErrorCode::OverrideCollisionWithAnotherDirective
351            }
352            Self::OverrideFromSelfError { .. } => ErrorCode::OverrideFromSelfError,
353            Self::OverrideLabelInvalid { .. } => ErrorCode::OverrideLabelInvalid,
354            Self::OverrideOnInterface { .. } => ErrorCode::OverrideOnInterface,
355            Self::OverrideSourceHasOverride { .. } => ErrorCode::OverrideSourceHasOverride,
356            Self::QueryRootMissing { .. } => ErrorCode::QueryRootMissing,
357            Self::ArgumentDefaultMismatch { .. } => ErrorCode::FieldArgumentDefaultMismatch,
358            Self::InputFieldDefaultMismatch { .. } => ErrorCode::InputFieldDefaultMismatch,
359            Self::InterfaceFieldNoImplem { .. } => ErrorCode::InterfaceFieldNoImplem,
360        }
361    }
362
363    pub(crate) fn append_message(self, appendix: impl Display) -> Self {
364        match self {
365            Self::EmptyMergedEnumType { message, locations } => Self::EmptyMergedEnumType {
366                message: format!("{message}{appendix}"),
367                locations,
368            },
369            Self::EnumValueMismatch { message } => Self::EnumValueMismatch {
370                message: format!("{message}{appendix}"),
371            },
372            Self::ExternalTypeMismatch { message } => Self::ExternalTypeMismatch {
373                message: format!("{message}{appendix}"),
374            },
375            Self::ExternalArgumentTypeMismatch { message } => Self::ExternalArgumentTypeMismatch {
376                message: format!("{message}{appendix}"),
377            },
378            Self::ExternalArgumentDefaultMismatch { message } => {
379                Self::ExternalArgumentDefaultMismatch {
380                    message: format!("{message}{appendix}"),
381                }
382            }
383            Self::InvalidGraphQL { message } => Self::InvalidGraphQL {
384                message: format!("{message}{appendix}"),
385            },
386            Self::DirectiveDefinitionInvalid { message } => Self::DirectiveDefinitionInvalid {
387                message: format!("{message}{appendix}"),
388            },
389            Self::TypeDefinitionInvalid { message } => Self::TypeDefinitionInvalid {
390                message: format!("{message}{appendix}"),
391            },
392            Self::InterfaceObjectUsageError { message } => Self::InterfaceObjectUsageError {
393                message: format!("{message}{appendix}"),
394            },
395            Self::InterfaceKeyMissingImplementationType { message } => {
396                Self::InterfaceKeyMissingImplementationType {
397                    message: format!("{message}{appendix}"),
398                }
399            }
400            Self::TypeKindMismatch { message } => Self::TypeKindMismatch {
401                message: format!("{message}{appendix}"),
402            },
403            Self::ShareableHasMismatchedRuntimeTypes { message } => {
404                Self::ShareableHasMismatchedRuntimeTypes {
405                    message: format!("{message}{appendix}"),
406                }
407            }
408            Self::SatisfiabilityError { message } => Self::SatisfiabilityError {
409                message: format!("{message}{appendix}"),
410            },
411            Self::MaxValidationSubgraphPathsExceeded { message } => {
412                Self::MaxValidationSubgraphPathsExceeded {
413                    message: format!("{message}{appendix}"),
414                }
415            }
416            Self::InternalError { message } => Self::InternalError {
417                message: format!("{message}{appendix}"),
418            },
419            Self::ExternalArgumentMissing { message } => Self::ExternalArgumentMissing {
420                message: format!("{message}{appendix}"),
421            },
422            Self::ExternalMissingOnBase { message } => Self::ExternalMissingOnBase {
423                message: format!("{message}{appendix}"),
424            },
425            Self::MergedDirectiveApplicationOnExternal { message } => {
426                Self::MergedDirectiveApplicationOnExternal {
427                    message: format!("{message}{appendix}"),
428                }
429            }
430            Self::LinkImportNameMismatch { message } => Self::LinkImportNameMismatch {
431                message: format!("{message}{appendix}"),
432            },
433            Self::InvalidFieldSharing { message, locations } => Self::InvalidFieldSharing {
434                message: format!("{message}{appendix}"),
435                locations,
436            },
437            Self::DirectiveCompositionError { message } => Self::DirectiveCompositionError {
438                message: format!("{message}{appendix}"),
439            },
440            Self::InconsistentInputObjectField { message } => Self::InconsistentInputObjectField {
441                message: format!("{message}{appendix}"),
442            },
443            Self::RequiredArgumentMissingInSomeSubgraph { message, locations } => {
444                Self::RequiredArgumentMissingInSomeSubgraph {
445                    message: format!("{message}{appendix}"),
446                    locations,
447                }
448            }
449            Self::RequiredInputFieldMissingInSomeSubgraph { message, locations } => {
450                Self::RequiredInputFieldMissingInSomeSubgraph {
451                    message: format!("{message}{appendix}"),
452                    locations,
453                }
454            }
455            Self::EmptyMergedInputType { message, locations } => Self::EmptyMergedInputType {
456                message: format!("{message}{appendix}"),
457                locations,
458            },
459            Self::InputFieldMergeFailed { message, locations } => Self::InputFieldMergeFailed {
460                message: format!("{message}{appendix}"),
461                locations,
462            },
463            Self::FieldArgumentTypeMismatch { message } => Self::FieldArgumentTypeMismatch {
464                message: format!("{message}{appendix}"),
465            },
466            Self::FieldTypeMismatch { message } => Self::FieldTypeMismatch {
467                message: format!("{message}{appendix}"),
468            },
469            Self::ContextualArgumentNotContextualInAllSubgraphs { message, locations } => {
470                Self::ContextualArgumentNotContextualInAllSubgraphs {
471                    message: format!("{message}{appendix}"),
472                    locations,
473                }
474            }
475            Self::ArgumentDefaultMismatch { message, locations } => Self::ArgumentDefaultMismatch {
476                message: format!("{message}{appendix}"),
477                locations,
478            },
479            Self::InputFieldDefaultMismatch { message, locations } => {
480                Self::InputFieldDefaultMismatch {
481                    message: format!("{message}{appendix}"),
482                    locations,
483                }
484            }
485            Self::InterfaceFieldNoImplem { message, locations } => Self::InterfaceFieldNoImplem {
486                message: format!("{message}{appendix}"),
487                locations,
488            },
489            // Remaining errors do not have an obvious way to appending a message, so we just return self.
490            Self::SubgraphError { .. }
491            | Self::MergeError { .. }
492            | Self::MergeValidationError { .. }
493            | Self::InvalidGraphQLName(..)
494            | Self::FromContextParseError { .. }
495            | Self::UnsupportedSpreadDirective { .. }
496            | Self::ExtensionWithNoBase { .. }
497            | Self::OverrideCollisionWithAnotherDirective { .. }
498            | Self::OverrideFromSelfError { .. }
499            | Self::OverrideLabelInvalid { .. }
500            | Self::OverrideOnInterface { .. }
501            | Self::OverrideSourceHasOverride { .. }
502            | Self::QueryRootMissing { .. } => self,
503        }
504    }
505
506    pub(crate) fn append_locations(
507        mut self,
508        new_locations: impl IntoIterator<Item = SubgraphLocation>,
509    ) -> Self {
510        match &mut self {
511            Self::SubgraphError { locations, .. }
512            | Self::EmptyMergedEnumType { locations, .. }
513            | Self::InputFieldMergeFailed { locations, .. }
514            | Self::ExtensionWithNoBase { locations, .. }
515            | Self::RequiredArgumentMissingInSomeSubgraph { locations, .. }
516            | Self::RequiredInputFieldMissingInSomeSubgraph { locations, .. }
517            | Self::EmptyMergedInputType { locations, .. }
518            | Self::InvalidFieldSharing { locations, .. }
519            | Self::MergeError { locations, .. }
520            | Self::ArgumentDefaultMismatch { locations, .. }
521            | Self::InputFieldDefaultMismatch { locations, .. } => locations.extend(new_locations),
522            // Remaining errors do not have an obvious way to appending locations, so we do nothing
523            _ => {}
524        }
525        self
526    }
527
528    pub fn locations(&self) -> &[SubgraphLocation] {
529        match self {
530            Self::SubgraphError { locations, .. }
531            | Self::EmptyMergedEnumType { locations, .. }
532            | Self::InputFieldMergeFailed { locations, .. }
533            | Self::ExtensionWithNoBase { locations, .. }
534            | Self::RequiredArgumentMissingInSomeSubgraph { locations, .. }
535            | Self::RequiredInputFieldMissingInSomeSubgraph { locations, .. }
536            | Self::EmptyMergedInputType { locations, .. }
537            | Self::InvalidFieldSharing { locations, .. }
538            | Self::MergeError { locations, .. }
539            | Self::ArgumentDefaultMismatch { locations, .. }
540            | Self::InputFieldDefaultMismatch { locations, .. }
541            | Self::InterfaceFieldNoImplem { locations, .. } => locations,
542            _ => &[],
543        }
544    }
545}
546
547impl SubgraphError {
548    pub fn to_composition_errors(&self) -> impl Iterator<Item = CompositionError> {
549        self.errors
550            .iter()
551            .map(move |error| CompositionError::SubgraphError {
552                subgraph: self.subgraph.clone(),
553                error: error.error.clone(),
554                locations: error
555                    .locations
556                    .iter()
557                    .map(|range| SubgraphLocation {
558                        subgraph: self.subgraph.clone(),
559                        range: range.clone(),
560                    })
561                    .collect(),
562            })
563    }
564}
565
566/* TODO(@tylerbloom): This is currently not needed. SingleFederation errors are aggregated using
567 * MultipleFederationErrors. This is then turned into a FederationError, then in a SubgraphError,
568 * and finally into a CompositionError. Not implementing this yet also ensures that any
569 * SingleFederationErrors that are intented on becoming SubgraphErrors still do.
570impl<E: Into<FederationError>> From<E> for SingleCompositionError {
571    fn from(_value: E) -> Self {
572        todo!()
573    }
574}
575*/
576
577#[derive(Debug, Clone, thiserror::Error)]
578pub enum SingleFederationError {
579    #[error(
580        "An internal error has occurred, please report this bug to Apollo.\n\nDetails: {message}"
581    )]
582    Internal { message: String },
583    #[error("An internal error has occurred, please report this bug to Apollo. Details: {0}")]
584    #[allow(private_interfaces)] // users should not inspect this.
585    InternalRebaseError(#[from] crate::operation::RebaseError),
586    // This is a known bug that will take time to fix, and does not require reporting.
587    #[error("{message}")]
588    InternalUnmergeableFields { message: String },
589    // InvalidGraphQL: We need to be able to modify the message text from apollo-compiler. So, we
590    //                 format the DiagnosticData into String here. We can add additional data as
591    //                 necessary.
592    #[error("{message}")]
593    InvalidGraphQL { message: String },
594    #[error(transparent)]
595    InvalidGraphQLName(#[from] InvalidNameError),
596    #[error("Subgraph invalid: {message}")]
597    InvalidSubgraph { message: String },
598    #[error("Operation name not found")]
599    UnknownOperation,
600    #[error("Must provide operation name if query contains multiple operations")]
601    OperationNameNotProvided,
602    #[error(r#"{message} in @fromContext substring "{context}""#)]
603    FromContextParseError { context: String, message: String },
604    #[error(
605        "Unsupported custom directive @{name} on fragment spread. Due to query transformations during planning, the router requires directives on fragment spreads to support both the FRAGMENT_SPREAD and INLINE_FRAGMENT locations."
606    )]
607    UnsupportedSpreadDirective { name: Name },
608    #[error("{message}")]
609    DirectiveDefinitionInvalid { message: String },
610    #[error("{message}")]
611    TypeDefinitionInvalid { message: String },
612    #[error("{message}")]
613    UnsupportedFederationDirective { message: String },
614    #[error("{message}")]
615    UnsupportedFederationVersion { message: String },
616    #[error("{message}")]
617    UnsupportedLinkedFeature { message: String },
618    #[error("{message}")]
619    UnknownFederationLinkVersion { message: String },
620    #[error("{message}")]
621    UnknownLinkVersion { message: String },
622    #[error(
623        "On type \"{target_type}\", for {application}: field {inner_coordinate} cannot be included because it has arguments (fields with argument are not allowed in @key)"
624    )]
625    KeyFieldsHasArgs {
626        target_type: Name,
627        application: String,
628        inner_coordinate: String,
629    },
630    #[error(
631        "On field \"{coordinate}\", for {application}: field {inner_coordinate} cannot be included because it has arguments (fields with argument are not allowed in @provides)"
632    )]
633    ProvidesFieldsHasArgs {
634        coordinate: String,
635        application: String,
636        inner_coordinate: String,
637    },
638    #[error("On field \"{coordinate}\", for {application}: {message}")]
639    ProvidesFieldsMissingExternal {
640        coordinate: String,
641        application: String,
642        message: String,
643    },
644    #[error("On field \"{coordinate}\", for {application}: {message}")]
645    RequiresFieldsMissingExternal {
646        coordinate: String,
647        application: String,
648        message: String,
649    },
650    #[error("{message}")]
651    KeyUnsupportedOnInterface { message: String },
652    #[error("{message}")]
653    ProvidesUnsupportedOnInterface { message: String },
654    #[error("{message}")]
655    RequiresUnsupportedOnInterface { message: String },
656    #[error(
657        "On type \"{target_type}\", for {application}: cannot have directive applications in the @key(fields:) argument but found {applied_directives}."
658    )]
659    KeyHasDirectiveInFieldsArg {
660        target_type: Name,
661        application: String,
662        applied_directives: String,
663    },
664    #[error(
665        "On field \"{coordinate}\", for {application}: cannot have directive applications in the @provides(fields:) argument but found {applied_directives}."
666    )]
667    ProvidesHasDirectiveInFieldsArg {
668        coordinate: String,
669        application: String,
670        applied_directives: String,
671    },
672    #[error(
673        "On field \"{coordinate}\", for {application}: cannot have directive applications in the @requires(fields:) argument but found {applied_directives}."
674    )]
675    RequiresHasDirectiveInFieldsArg {
676        coordinate: String,
677        application: String,
678        applied_directives: String,
679    },
680    #[error("{message}")]
681    ExternalUnused { message: String },
682    #[error(
683        "Type {type_name} contains only external fields and all those fields are all unused (they do not appear in any @key, @provides or @requires)."
684    )]
685    TypeWithOnlyUnusedExternal { type_name: Name },
686    #[error("{message}")]
687    ProvidesOnNonObjectField { message: String },
688    #[error(
689        "On type \"{target_type}\", for {application}: Invalid value for argument \"fields\": must be a string."
690    )]
691    KeyInvalidFieldsType {
692        target_type: Name,
693        application: String,
694    },
695    #[error(
696        "On field \"{coordinate}\", for {application}: Invalid value for argument \"fields\": must be a string."
697    )]
698    ProvidesInvalidFieldsType {
699        coordinate: String,
700        application: String,
701    },
702    #[error(
703        "On field \"{coordinate}\", for {application}: Invalid value for argument \"fields\": must be a string."
704    )]
705    RequiresInvalidFieldsType {
706        coordinate: String,
707        application: String,
708    },
709    #[error("On type \"{target_type}\", for {application}: {message}")]
710    KeyInvalidFields {
711        target_type: Name,
712        application: String,
713        message: String,
714    },
715    #[error("On field \"{coordinate}\", for {application}: {message}")]
716    ProvidesInvalidFields {
717        coordinate: String,
718        application: String,
719        message: String,
720    },
721    #[error("On field \"{coordinate}\", for {application}: {message}")]
722    RequiresInvalidFields {
723        coordinate: String,
724        application: String,
725        message: String,
726    },
727    #[error("On type \"{target_type}\", for {application}: {message}")]
728    KeyFieldsSelectInvalidType {
729        target_type: Name,
730        application: String,
731        message: String,
732    },
733    #[error(
734        "The schema has a type named \"{expected_name}\" but it is not set as the query root type (\"{found_name}\" is instead): this is not supported by federation. If a root type does not use its default name, there should be no other type with that default name."
735    )]
736    RootQueryUsed {
737        expected_name: Name,
738        found_name: Name,
739    },
740    #[error(
741        "The schema has a type named \"{expected_name}\" but it is not set as the mutation root type (\"{found_name}\" is instead): this is not supported by federation. If a root type does not use its default name, there should be no other type with that default name."
742    )]
743    RootMutationUsed {
744        expected_name: Name,
745        found_name: Name,
746    },
747    #[error(
748        "The schema has a type named \"{expected_name}\" but it is not set as the subscription root type (\"{found_name}\" is instead): this is not supported by federation. If a root type does not use its default name, there should be no other type with that default name."
749    )]
750    RootSubscriptionUsed {
751        expected_name: Name,
752        found_name: Name,
753    },
754    #[error("{message}")]
755    InvalidSubgraphName { message: String },
756    #[error("{message}")]
757    NoQueries { message: String },
758    #[error("{message}")]
759    InterfaceFieldNoImplem { message: String },
760    #[error("{message}")]
761    ExternalTypeMismatch { message: String },
762    #[error("{message}")]
763    ExternalCollisionWithAnotherDirective { message: String },
764    #[error("{message}")]
765    ExternalArgumentMissing { message: String },
766    #[error("{message}")]
767    ExternalArgumentTypeMismatch { message: String },
768    #[error("{message}")]
769    ExternalArgumentDefaultMismatch { message: String },
770    #[error("{message}")]
771    ExternalOnInterface { message: String },
772    #[error("{message}")]
773    MergedDirectiveApplicationOnExternal { message: String },
774    #[error("{message}")]
775    FieldTypeMismatch { message: String },
776    #[error("{message}")]
777    FieldArgumentTypeMismatch { message: String },
778    #[error("{message}")]
779    InputFieldDefaultMismatch { message: String },
780    #[error("{message}")]
781    FieldArgumentDefaultMismatch { message: String },
782    #[error("{message}")]
783    ExtensionWithNoBase { message: String },
784    #[error("{message}")]
785    ExternalMissingOnBase { message: String },
786    #[error("{message}")]
787    InvalidFieldSharing { message: String },
788    #[error("{message}")]
789    InvalidShareableUsage { message: String },
790    #[error("{message}")]
791    InvalidLinkDirectiveUsage { message: String },
792    #[error("{message}")]
793    InvalidLinkIdentifier { message: String },
794    #[error("{message}")]
795    ReferencedInaccessible {
796        message: String,
797        links: InaccessibleCompositionLinks,
798    },
799    #[error("{message}")]
800    DefaultValueUsesInaccessible {
801        message: String,
802        links: InaccessibleCompositionLinks,
803    },
804    #[error("{message}")]
805    QueryRootTypeInaccessible {
806        message: String,
807        links: InaccessibleCompositionLinks,
808    },
809    #[error("{message}")]
810    RequiredInaccessible {
811        message: String,
812        links: InaccessibleCompositionLinks,
813    },
814    #[error("{message}")]
815    ImplementedByInaccessible {
816        message: String,
817        links: InaccessibleCompositionLinks,
818    },
819    #[error("{message}")]
820    DisallowedInaccessible {
821        message: String,
822        links: InaccessibleCompositionLinks,
823    },
824    #[error("{message}")]
825    OnlyInaccessibleChildren {
826        message: String,
827        links: InaccessibleCompositionLinks,
828    },
829    #[error("{message}")]
830    RequiredInputFieldMissingInSomeSubgraph { message: String },
831    #[error("{message}")]
832    RequiredArgumentMissingInSomeSubgraph { message: String },
833    #[error("{message}")]
834    EmptyMergedInputType { message: String },
835    #[error("{message}")]
836    EnumValueMismatch { message: String },
837    #[error("{message}")]
838    EmptyMergedEnumType { message: String },
839    #[error("{message}")]
840    ShareableHasMismatchedRuntimeTypes { message: String },
841    #[error("{message}")]
842    SatisfiabilityError { message: String },
843    #[error("{message}")]
844    OverrideFromSelfError { message: String },
845    #[error("{message}")]
846    OverrideSourceHasOverride { message: String },
847    #[error("{message}")]
848    OverrideCollisionWithAnotherDirective { message: String },
849    #[error("{message}")]
850    OverrideOnInterface { message: String },
851    #[error("{message}")]
852    UnsupportedFeature {
853        message: String,
854        kind: UnsupportedFeatureKind,
855    },
856    #[error("{message}")]
857    InvalidFederationSupergraph { message: String },
858    #[error("{message}")]
859    DownstreamServiceError { message: String },
860    #[error("{message}")]
861    DirectiveCompositionError { message: String },
862    #[error("{message}")]
863    InterfaceObjectUsageError { message: String },
864    #[error("{message}")]
865    InterfaceKeyNotOnImplementation { message: String },
866    #[error("{message}")]
867    InterfaceKeyMissingImplementationType { message: String },
868    #[error("@defer is not supported on subscriptions")]
869    DeferredSubscriptionUnsupported,
870    #[error("Duplicate @defer label {label:?}: labels must be unique within an operation")]
871    DuplicateDeferLabel { label: String },
872    #[error("{message}")]
873    QueryPlanComplexityExceeded { message: String },
874    #[error("the caller requested cancellation")]
875    PlanningCancelled,
876    #[error("No plan was found when subgraphs were disabled")]
877    NoPlanFoundWithDisabledSubgraphs,
878    #[error("Context name \"{name}\" may not contain an underscore.")]
879    ContextNameContainsUnderscore { name: String },
880    #[error("Context name \"{name}\" is invalid. It should have only alphanumeric characters.")]
881    ContextNameInvalid { name: String },
882    #[error("{message}")]
883    ContextNotSet { message: String },
884    #[error("{message}")]
885    NoContextReferenced { message: String },
886    #[error("{message}")]
887    NoSelectionForContext { message: String },
888    #[error("{message}")]
889    ContextNoResolvableKey { message: String },
890    #[error("@cost cannot be applied to interface \"{interface}.{field}\"")]
891    CostAppliedToInterfaceField { interface: Name, field: Name },
892    #[error("{message}")]
893    ContextSelectionInvalid { message: String },
894    #[error("{message}")]
895    ListSizeAppliedToNonList { message: String },
896    #[error("{message}")]
897    ListSizeInvalidAssumedSize { message: String },
898    #[error("{message}")]
899    ListSizeInvalidSlicingArgument { message: String },
900    #[error("{message}")]
901    ListSizeInvalidSizedField { message: String },
902    #[error("{message}")]
903    InvalidTagName { message: String },
904    /// `@cacheTag` directive validation errors (subgraph)
905    #[error("cacheTag format is invalid: {message}")]
906    CacheTagInvalidFormat { message: String },
907    #[error(
908        "error on field \"{field_name}\" on type \"{type_name}\": cacheTag can only apply on root fields or entity types"
909    )]
910    CacheTagAppliedToNonRootField { type_name: Name, field_name: Name },
911    #[error("cacheTag applied on root fields can only reference arguments in format using $args")]
912    CacheTagInvalidFormatArgumentOnRootField,
913    #[error("cacheTag applied on types can only reference arguments in format using $key")]
914    CacheTagInvalidFormatArgumentOnEntity { type_name: Name, format: String },
915    #[error(
916        "Object \"{0}\" is not an entity. cacheTag can only apply on resolvable entities, object containing at least 1 @key directive and resolvable"
917    )]
918    CacheTagEntityNotResolvable(Name),
919    #[error("{message}")]
920    QueryRootMissing { message: String },
921    #[error(
922        "Invalid use of @{directive_name} on {kind} \"{coordinate}\": @{directive_name} cannot be applied on interfaces, interface fields and interface objects"
923    )]
924    AuthRequirementsAppliedOnInterface {
925        directive_name: String,
926        kind: String,
927        coordinate: String,
928    },
929    #[error("{message}")]
930    MissingTransitiveAuthRequirements { message: String },
931}
932
933impl SingleFederationError {
934    pub fn code(&self) -> ErrorCode {
935        match self {
936            SingleFederationError::Internal { .. } => ErrorCode::Internal,
937            SingleFederationError::InternalRebaseError { .. } => ErrorCode::Internal,
938            SingleFederationError::InternalUnmergeableFields { .. } => ErrorCode::Internal,
939            SingleFederationError::InvalidGraphQL { .. }
940            | SingleFederationError::InvalidGraphQLName(_) => ErrorCode::InvalidGraphQL,
941            SingleFederationError::InvalidSubgraph { .. } => ErrorCode::InvalidGraphQL,
942            // Technically it's not invalid graphql, but it is invalid syntax inside graphql...
943            SingleFederationError::FromContextParseError { .. } => ErrorCode::InvalidGraphQL,
944            // TODO(@goto-bus-stop): this should have a different error code: it's not invalid,
945            // just unsupported due to internal limitations.
946            SingleFederationError::UnsupportedSpreadDirective { .. } => ErrorCode::InvalidGraphQL,
947            // TODO(@goto-bus-stop): this should have a different error code: it's not the graphql
948            // that's invalid, but the operation name
949            SingleFederationError::UnknownOperation => ErrorCode::InvalidGraphQL,
950            SingleFederationError::OperationNameNotProvided => ErrorCode::InvalidGraphQL,
951            SingleFederationError::DirectiveDefinitionInvalid { .. } => {
952                ErrorCode::DirectiveDefinitionInvalid
953            }
954            SingleFederationError::TypeDefinitionInvalid { .. } => ErrorCode::TypeDefinitionInvalid,
955            SingleFederationError::UnsupportedFederationDirective { .. } => {
956                ErrorCode::UnsupportedFederationDirective
957            }
958            SingleFederationError::UnsupportedFederationVersion { .. } => {
959                ErrorCode::UnsupportedFederationVersion
960            }
961            SingleFederationError::UnsupportedLinkedFeature { .. } => {
962                ErrorCode::UnsupportedLinkedFeature
963            }
964            SingleFederationError::UnknownFederationLinkVersion { .. } => {
965                ErrorCode::UnknownFederationLinkVersion
966            }
967            SingleFederationError::UnknownLinkVersion { .. } => ErrorCode::UnknownLinkVersion,
968            SingleFederationError::KeyFieldsHasArgs { .. } => ErrorCode::KeyFieldsHasArgs,
969            SingleFederationError::ProvidesFieldsHasArgs { .. } => ErrorCode::ProvidesFieldsHasArgs,
970            SingleFederationError::ProvidesFieldsMissingExternal { .. } => {
971                ErrorCode::ProvidesFieldsMissingExternal
972            }
973            SingleFederationError::RequiresFieldsMissingExternal { .. } => {
974                ErrorCode::RequiresFieldsMissingExternal
975            }
976            SingleFederationError::KeyUnsupportedOnInterface { .. } => {
977                ErrorCode::KeyUnsupportedOnInterface
978            }
979            SingleFederationError::ProvidesUnsupportedOnInterface { .. } => {
980                ErrorCode::ProvidesUnsupportedOnInterface
981            }
982            SingleFederationError::RequiresUnsupportedOnInterface { .. } => {
983                ErrorCode::RequiresUnsupportedOnInterface
984            }
985            SingleFederationError::KeyHasDirectiveInFieldsArg { .. } => {
986                ErrorCode::KeyDirectiveInFieldsArgs
987            }
988            SingleFederationError::ProvidesHasDirectiveInFieldsArg { .. } => {
989                ErrorCode::ProvidesDirectiveInFieldsArgs
990            }
991            SingleFederationError::RequiresHasDirectiveInFieldsArg { .. } => {
992                ErrorCode::RequiresDirectiveInFieldsArgs
993            }
994            SingleFederationError::ExternalUnused { .. } => ErrorCode::ExternalUnused,
995            SingleFederationError::TypeWithOnlyUnusedExternal { .. } => {
996                ErrorCode::TypeWithOnlyUnusedExternal
997            }
998            SingleFederationError::ProvidesOnNonObjectField { .. } => {
999                ErrorCode::ProvidesOnNonObjectField
1000            }
1001            SingleFederationError::KeyInvalidFieldsType { .. } => ErrorCode::KeyInvalidFieldsType,
1002            SingleFederationError::ProvidesInvalidFieldsType { .. } => {
1003                ErrorCode::ProvidesInvalidFieldsType
1004            }
1005            SingleFederationError::RequiresInvalidFieldsType { .. } => {
1006                ErrorCode::RequiresInvalidFieldsType
1007            }
1008            SingleFederationError::KeyInvalidFields { .. } => ErrorCode::KeyInvalidFields,
1009            SingleFederationError::ProvidesInvalidFields { .. } => ErrorCode::ProvidesInvalidFields,
1010            SingleFederationError::RequiresInvalidFields { .. } => ErrorCode::RequiresInvalidFields,
1011            SingleFederationError::KeyFieldsSelectInvalidType { .. } => {
1012                ErrorCode::KeyFieldsSelectInvalidType
1013            }
1014            SingleFederationError::RootQueryUsed { .. } => ErrorCode::RootQueryUsed,
1015            SingleFederationError::RootMutationUsed { .. } => ErrorCode::RootMutationUsed,
1016            SingleFederationError::RootSubscriptionUsed { .. } => ErrorCode::RootSubscriptionUsed,
1017            SingleFederationError::InvalidSubgraphName { .. } => ErrorCode::InvalidSubgraphName,
1018            SingleFederationError::NoQueries { .. } => ErrorCode::NoQueries,
1019            SingleFederationError::InterfaceFieldNoImplem { .. } => {
1020                ErrorCode::InterfaceFieldNoImplem
1021            }
1022            SingleFederationError::ExternalTypeMismatch { .. } => ErrorCode::ExternalTypeMismatch,
1023            SingleFederationError::ExternalCollisionWithAnotherDirective { .. } => {
1024                ErrorCode::ExternalCollisionWithAnotherDirective
1025            }
1026            SingleFederationError::ExternalArgumentMissing { .. } => {
1027                ErrorCode::ExternalArgumentMissing
1028            }
1029            SingleFederationError::ExternalArgumentTypeMismatch { .. } => {
1030                ErrorCode::ExternalArgumentTypeMismatch
1031            }
1032            SingleFederationError::ExternalArgumentDefaultMismatch { .. } => {
1033                ErrorCode::ExternalArgumentDefaultMismatch
1034            }
1035            SingleFederationError::ExternalOnInterface { .. } => ErrorCode::ExternalOnInterface,
1036            SingleFederationError::MergedDirectiveApplicationOnExternal { .. } => {
1037                ErrorCode::MergedDirectiveApplicationOnExternal
1038            }
1039            SingleFederationError::FieldTypeMismatch { .. } => ErrorCode::FieldTypeMismatch,
1040            SingleFederationError::FieldArgumentTypeMismatch { .. } => {
1041                ErrorCode::FieldArgumentTypeMismatch
1042            }
1043            SingleFederationError::InputFieldDefaultMismatch { .. } => {
1044                ErrorCode::InputFieldDefaultMismatch
1045            }
1046            SingleFederationError::FieldArgumentDefaultMismatch { .. } => {
1047                ErrorCode::FieldArgumentDefaultMismatch
1048            }
1049            SingleFederationError::ExtensionWithNoBase { .. } => ErrorCode::ExtensionWithNoBase,
1050            SingleFederationError::ExternalMissingOnBase { .. } => ErrorCode::ExternalMissingOnBase,
1051            SingleFederationError::InvalidFieldSharing { .. } => ErrorCode::InvalidFieldSharing,
1052            SingleFederationError::InvalidShareableUsage { .. } => ErrorCode::InvalidShareableUsage,
1053            SingleFederationError::InvalidLinkDirectiveUsage { .. } => {
1054                ErrorCode::InvalidLinkDirectiveUsage
1055            }
1056            SingleFederationError::InvalidLinkIdentifier { .. } => ErrorCode::InvalidLinkIdentifier,
1057            SingleFederationError::ReferencedInaccessible { .. } => {
1058                ErrorCode::ReferencedInaccessible
1059            }
1060            SingleFederationError::DefaultValueUsesInaccessible { .. } => {
1061                ErrorCode::DefaultValueUsesInaccessible
1062            }
1063            SingleFederationError::QueryRootTypeInaccessible { .. } => {
1064                ErrorCode::QueryRootTypeInaccessible
1065            }
1066            SingleFederationError::RequiredInaccessible { .. } => ErrorCode::RequiredInaccessible,
1067            SingleFederationError::ImplementedByInaccessible { .. } => {
1068                ErrorCode::ImplementedByInaccessible
1069            }
1070            SingleFederationError::DisallowedInaccessible { .. } => {
1071                ErrorCode::DisallowedInaccessible
1072            }
1073            SingleFederationError::OnlyInaccessibleChildren { .. } => {
1074                ErrorCode::OnlyInaccessibleChildren
1075            }
1076            SingleFederationError::RequiredInputFieldMissingInSomeSubgraph { .. } => {
1077                ErrorCode::RequiredInputFieldMissingInSomeSubgraph
1078            }
1079            SingleFederationError::RequiredArgumentMissingInSomeSubgraph { .. } => {
1080                ErrorCode::RequiredArgumentMissingInSomeSubgraph
1081            }
1082            SingleFederationError::EmptyMergedInputType { .. } => ErrorCode::EmptyMergedInputType,
1083            SingleFederationError::EnumValueMismatch { .. } => ErrorCode::EnumValueMismatch,
1084            SingleFederationError::EmptyMergedEnumType { .. } => ErrorCode::EmptyMergedEnumType,
1085            SingleFederationError::ShareableHasMismatchedRuntimeTypes { .. } => {
1086                ErrorCode::ShareableHasMismatchedRuntimeTypes
1087            }
1088            SingleFederationError::SatisfiabilityError { .. } => ErrorCode::SatisfiabilityError,
1089            SingleFederationError::OverrideFromSelfError { .. } => ErrorCode::OverrideFromSelfError,
1090            SingleFederationError::OverrideSourceHasOverride { .. } => {
1091                ErrorCode::OverrideSourceHasOverride
1092            }
1093            SingleFederationError::OverrideCollisionWithAnotherDirective { .. } => {
1094                ErrorCode::OverrideCollisionWithAnotherDirective
1095            }
1096            SingleFederationError::OverrideOnInterface { .. } => ErrorCode::OverrideOnInterface,
1097            SingleFederationError::UnsupportedFeature { .. } => ErrorCode::UnsupportedFeature,
1098            SingleFederationError::InvalidFederationSupergraph { .. } => {
1099                ErrorCode::InvalidFederationSupergraph
1100            }
1101            SingleFederationError::DownstreamServiceError { .. } => {
1102                ErrorCode::DownstreamServiceError
1103            }
1104            SingleFederationError::DirectiveCompositionError { .. } => {
1105                ErrorCode::DirectiveCompositionError
1106            }
1107            SingleFederationError::InterfaceObjectUsageError { .. } => {
1108                ErrorCode::InterfaceObjectUsageError
1109            }
1110            SingleFederationError::InterfaceKeyNotOnImplementation { .. } => {
1111                ErrorCode::InterfaceKeyNotOnImplementation
1112            }
1113            SingleFederationError::InterfaceKeyMissingImplementationType { .. } => {
1114                ErrorCode::InterfaceKeyMissingImplementationType
1115            }
1116            SingleFederationError::DeferredSubscriptionUnsupported => ErrorCode::Internal,
1117            SingleFederationError::DuplicateDeferLabel { .. } => ErrorCode::InvalidGraphQL,
1118            SingleFederationError::QueryPlanComplexityExceeded { .. } => {
1119                ErrorCode::QueryPlanComplexityExceededError
1120            }
1121            SingleFederationError::PlanningCancelled => ErrorCode::Internal,
1122            SingleFederationError::NoPlanFoundWithDisabledSubgraphs => {
1123                ErrorCode::NoPlanFoundWithDisabledSubgraphs
1124            }
1125            SingleFederationError::ContextNameContainsUnderscore { .. } => {
1126                ErrorCode::ContextNameContainsUnderscore
1127            }
1128            SingleFederationError::ContextNameInvalid { .. } => ErrorCode::ContextNameInvalid,
1129            SingleFederationError::ContextNotSet { .. } => ErrorCode::ContextNotSet,
1130            SingleFederationError::NoContextReferenced { .. } => ErrorCode::NoContextReferenced,
1131            SingleFederationError::NoSelectionForContext { .. } => ErrorCode::NoSelectionForContext,
1132            SingleFederationError::ContextNoResolvableKey { .. } => {
1133                ErrorCode::ContextNoResolvableKey
1134            }
1135            SingleFederationError::ContextSelectionInvalid { .. } => {
1136                ErrorCode::ContextSelectionInvalid
1137            }
1138            SingleFederationError::CostAppliedToInterfaceField { .. } => {
1139                ErrorCode::CostAppliedToInterfaceField
1140            }
1141            SingleFederationError::ListSizeAppliedToNonList { .. } => {
1142                ErrorCode::ListSizeAppliedToNonList
1143            }
1144            SingleFederationError::ListSizeInvalidAssumedSize { .. } => {
1145                ErrorCode::ListSizeInvalidAssumedSize
1146            }
1147            SingleFederationError::ListSizeInvalidSlicingArgument { .. } => {
1148                ErrorCode::ListSizeInvalidSlicingArgument
1149            }
1150            SingleFederationError::ListSizeInvalidSizedField { .. } => {
1151                ErrorCode::ListSizeInvalidSizedField
1152            }
1153            #[allow(unused)]
1154            SingleFederationError::InvalidFieldSharing { .. } => ErrorCode::InvalidFieldSharing,
1155            SingleFederationError::InvalidTagName { .. } => ErrorCode::InvalidTagName,
1156            SingleFederationError::CacheTagInvalidFormat { .. } => ErrorCode::CacheTagInvalidFormat,
1157            SingleFederationError::CacheTagAppliedToNonRootField { .. } => {
1158                ErrorCode::CacheTagAppliedToNonRootField
1159            }
1160            SingleFederationError::CacheTagInvalidFormatArgumentOnRootField => {
1161                ErrorCode::CacheTagInvalidFormatArgumentOnRootField
1162            }
1163            SingleFederationError::CacheTagInvalidFormatArgumentOnEntity { .. } => {
1164                ErrorCode::CacheTagInvalidFormatArgumentOnEntity
1165            }
1166            SingleFederationError::CacheTagEntityNotResolvable { .. } => {
1167                ErrorCode::CacheTagEntityNotResolvable
1168            }
1169            SingleFederationError::QueryRootMissing { .. } => ErrorCode::QueryRootMissing,
1170            SingleFederationError::AuthRequirementsAppliedOnInterface { .. } => {
1171                ErrorCode::AuthRequirementsAppliedOnInterface
1172            }
1173            SingleFederationError::MissingTransitiveAuthRequirements { .. } => {
1174                ErrorCode::MissingTransitiveAuthRequirements
1175            }
1176        }
1177    }
1178
1179    pub fn code_string(&self) -> String {
1180        self.code().definition().code().to_string()
1181    }
1182
1183    pub(crate) fn root_already_used(
1184        operation_type: OperationType,
1185        expected_name: Name,
1186        found_name: Name,
1187    ) -> Self {
1188        match operation_type {
1189            OperationType::Query => Self::RootQueryUsed {
1190                expected_name,
1191                found_name,
1192            },
1193            OperationType::Mutation => Self::RootMutationUsed {
1194                expected_name,
1195                found_name,
1196            },
1197            OperationType::Subscription => Self::RootSubscriptionUsed {
1198                expected_name,
1199                found_name,
1200            },
1201        }
1202    }
1203}
1204
1205impl From<InvalidNameError> for FederationError {
1206    fn from(err: InvalidNameError) -> Self {
1207        SingleFederationError::from(err).into()
1208    }
1209}
1210
1211impl From<FederationSpecError> for FederationError {
1212    fn from(err: FederationSpecError) -> Self {
1213        // TODO: When we get around to finishing the composition port, we should really switch it to
1214        // using FederationError instead of FederationSpecError.
1215        let message = err.to_string();
1216        match err {
1217            FederationSpecError::UnsupportedVersionError { .. } => {
1218                SingleFederationError::UnsupportedFederationVersion { message }.into()
1219            }
1220            FederationSpecError::UnsupportedFederationDirective { .. } => {
1221                SingleFederationError::UnsupportedFederationDirective { message }.into()
1222            }
1223            FederationSpecError::InvalidGraphQLName(message) => message.into(),
1224        }
1225    }
1226}
1227
1228#[derive(Debug, Clone, thiserror::Error, Default)]
1229pub struct MultipleFederationErrors {
1230    pub(crate) errors: Vec<SingleFederationError>,
1231}
1232
1233impl MultipleFederationErrors {
1234    pub fn new() -> Self {
1235        Self { errors: vec![] }
1236    }
1237
1238    pub fn push(&mut self, error: FederationError) {
1239        match error {
1240            FederationError::SingleFederationError(error) => {
1241                self.errors.push(error);
1242            }
1243            FederationError::MultipleFederationErrors(errors) => {
1244                self.errors.extend(errors.errors);
1245            }
1246            FederationError::AggregateFederationError(errors) => {
1247                self.errors.extend(errors.causes);
1248            }
1249        }
1250    }
1251
1252    pub(crate) fn and_try(mut self, other: Result<(), FederationError>) -> Self {
1253        match other {
1254            Ok(_) => self,
1255            Err(e) => {
1256                self.push(e);
1257                self
1258            }
1259        }
1260    }
1261}
1262
1263impl Display for MultipleFederationErrors {
1264    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1265        write!(f, "The following errors occurred:")?;
1266        for error in &self.errors {
1267            write!(f, "\n  - ")?;
1268            for c in error.to_string().chars() {
1269                if c == '\n' {
1270                    write!(f, "\n    ")?;
1271                } else {
1272                    f.write_char(c)?;
1273                }
1274            }
1275        }
1276        Ok(())
1277    }
1278}
1279
1280impl FromIterator<SingleFederationError> for MultipleFederationErrors {
1281    fn from_iter<T: IntoIterator<Item = SingleFederationError>>(iter: T) -> Self {
1282        Self {
1283            errors: iter.into_iter().collect(),
1284        }
1285    }
1286}
1287
1288#[derive(Debug, Clone, thiserror::Error)]
1289pub struct AggregateFederationError {
1290    pub code: String,
1291    pub message: String,
1292    pub causes: Vec<SingleFederationError>,
1293}
1294
1295impl Display for AggregateFederationError {
1296    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1297        write!(f, "[{}] {}\nCaused by:", self.code, self.message)?;
1298        for error in &self.causes {
1299            write!(f, "\n\n  - ")?;
1300            for c in error.to_string().chars() {
1301                if c == '\n' {
1302                    write!(f, "\n    ")?;
1303                } else {
1304                    f.write_char(c)?;
1305                }
1306            }
1307        }
1308        Ok(())
1309    }
1310}
1311
1312// PORT_NOTE: Often times, JS functions would either throw/return a GraphQLError, return a vector
1313// of GraphQLErrors, or take a vector of GraphQLErrors and group them together under an
1314// AggregateGraphQLError which itself would have a specific error message and code, and throw that.
1315// We represent all these cases with an enum, and delegate to the members.
1316#[derive(Clone, thiserror::Error)]
1317pub enum FederationError {
1318    #[error(transparent)]
1319    SingleFederationError(#[from] SingleFederationError),
1320    #[error(transparent)]
1321    MultipleFederationErrors(#[from] MultipleFederationErrors),
1322    #[error(transparent)]
1323    AggregateFederationError(#[from] AggregateFederationError),
1324}
1325
1326impl std::fmt::Debug for FederationError {
1327    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1328        match self {
1329            Self::SingleFederationError(inner) => std::fmt::Debug::fmt(inner, f),
1330            Self::MultipleFederationErrors(inner) => std::fmt::Debug::fmt(inner, f),
1331            Self::AggregateFederationError(inner) => std::fmt::Debug::fmt(inner, f),
1332        }
1333    }
1334}
1335
1336impl From<DiagnosticList> for FederationError {
1337    fn from(value: DiagnosticList) -> Self {
1338        let errors: Vec<_> = value
1339            .iter()
1340            .map(|d| SingleFederationError::InvalidGraphQL {
1341                message: d.to_string(),
1342            })
1343            .collect();
1344        match errors.len().cmp(&1) {
1345            Ordering::Less => internal_error!("diagnostic list is unexpectedly empty"),
1346            Ordering::Equal => errors[0].clone().into(),
1347            Ordering::Greater => MultipleFederationErrors { errors }.into(),
1348        }
1349    }
1350}
1351
1352impl<T> From<WithErrors<T>> for FederationError {
1353    fn from(value: WithErrors<T>) -> Self {
1354        value.errors.into()
1355    }
1356}
1357
1358// Used for when we condition on a type `T: TryInto<U>`, but we have an infallible conversion of
1359// `T: Into<U>`. This allows us to unwrap the `Result<U, Infallible>` with `?`.
1360impl From<std::convert::Infallible> for FederationError {
1361    fn from(_: std::convert::Infallible) -> Self {
1362        unreachable!("Infallible should never be converted to FederationError")
1363    }
1364}
1365
1366impl FederationError {
1367    pub fn internal(message: impl Into<String>) -> Self {
1368        SingleFederationError::Internal {
1369            message: message.into(),
1370        }
1371        .into()
1372    }
1373
1374    pub fn merge(self, other: Self) -> Self {
1375        let mut result = MultipleFederationErrors::new();
1376        result.push(self);
1377        result.push(other);
1378        result.into()
1379    }
1380
1381    pub fn into_errors(self) -> Vec<SingleFederationError> {
1382        match self {
1383            FederationError::SingleFederationError(e) => vec![e],
1384            FederationError::MultipleFederationErrors(e) => e.errors,
1385            FederationError::AggregateFederationError(e) => e.causes,
1386        }
1387    }
1388
1389    pub fn errors(&self) -> Vec<&SingleFederationError> {
1390        match self {
1391            FederationError::SingleFederationError(e) => vec![e],
1392            FederationError::MultipleFederationErrors(e) => e.errors.iter().collect(),
1393            FederationError::AggregateFederationError(e) => e.causes.iter().collect(),
1394        }
1395    }
1396
1397    pub fn has_invalid_graphql_error(&self) -> bool {
1398        self.errors()
1399            .into_iter()
1400            .any(|e| matches!(e, SingleFederationError::InvalidGraphQL { .. }))
1401    }
1402}
1403
1404// Similar to `multi_try` crate, but with `FederationError` instead of `Vec<E>`.
1405pub trait MultiTry<U> {
1406    type Output;
1407
1408    fn and_try(self, other: Result<U, FederationError>) -> Self::Output;
1409}
1410
1411impl<U> MultiTry<U> for Result<(), FederationError> {
1412    type Output = Result<U, FederationError>;
1413
1414    fn and_try(self, other: Result<U, FederationError>) -> Result<U, FederationError> {
1415        match (self, other) {
1416            (Ok(_a), Ok(b)) => Ok(b),
1417            (Ok(_a), Err(b)) => Err(b),
1418            (Err(a), Ok(_b)) => Err(a),
1419            (Err(a), Err(b)) => Err(a.merge(b)),
1420        }
1421    }
1422}
1423
1424pub trait MultiTryAll: Sized + Iterator {
1425    /// Apply `predicate` on all elements of the iterator, collecting all errors (if any).
1426    /// - Returns Ok(()), if all elements are Ok.
1427    /// - Otherwise, returns a FederationError with all errors.
1428    /// - Note: Not to be confused with `try_for_each`, which stops on the first error.
1429    fn try_for_all<F>(self, mut predicate: F) -> Result<(), FederationError>
1430    where
1431        F: FnMut(Self::Item) -> Result<(), FederationError>,
1432    {
1433        let mut errors = MultipleFederationErrors::new();
1434        for item in self {
1435            match predicate(item) {
1436                Ok(()) => {}
1437                Err(e) => errors.push(e),
1438            }
1439        }
1440        errors.into_result()
1441    }
1442}
1443
1444impl<I: Iterator> MultiTryAll for I {}
1445
1446impl MultipleFederationErrors {
1447    /// Converts into `Result<(), FederationError>`.
1448    /// - The return value can be either Ok, Err with a SingleFederationError or MultipleFederationErrors,
1449    ///   depending on the number of errors in the input.
1450    pub fn into_result(self) -> Result<(), FederationError> {
1451        match self.errors.len().cmp(&1) {
1452            Ordering::Less => Ok(()),
1453            Ordering::Equal => Err(self.errors[0].clone().into()),
1454            Ordering::Greater => Err(self.into()),
1455        }
1456    }
1457}
1458
1459// We didn't track errors addition precisely pre-2.0 and tracking it now has an unclear ROI, so we
1460// just mark all the error code that predates 2.0 as 0.x.
1461const FED1_CODE: &str = "0.x";
1462
1463#[derive(Debug, Clone)]
1464pub struct ErrorCodeMetadata {
1465    pub added_in: &'static str,
1466    pub replaces: &'static [&'static str],
1467}
1468
1469#[derive(Debug)]
1470pub struct ErrorCodeDefinition {
1471    code: String,
1472    // PORT_NOTE: Known as "description" in the JS code. The name was changed to distinguish it from
1473    // Error.description().
1474    doc_description: String,
1475    metadata: ErrorCodeMetadata,
1476}
1477
1478impl ErrorCodeDefinition {
1479    fn new(code: String, doc_description: String, metadata: Option<ErrorCodeMetadata>) -> Self {
1480        Self {
1481            code,
1482            doc_description,
1483            metadata: metadata.unwrap_or_else(|| DEFAULT_METADATA.clone()),
1484        }
1485    }
1486
1487    pub fn code(&self) -> &str {
1488        &self.code
1489    }
1490
1491    pub fn doc_description(&self) -> &str {
1492        &self.doc_description
1493    }
1494
1495    pub fn metadata(&self) -> &ErrorCodeMetadata {
1496        &self.metadata
1497    }
1498}
1499
1500/*
1501 * Most codes currently originate from the initial fed 2 release so we use this for convenience.
1502 * This can be changed later, inline versions everywhere, if that becomes irrelevant.
1503 */
1504static DEFAULT_METADATA: ErrorCodeMetadata = ErrorCodeMetadata {
1505    added_in: "2.0.0",
1506    replaces: &[],
1507};
1508
1509struct ErrorCodeCategory<TElement: Clone + Into<String>> {
1510    // Fn(element: TElement) -> String
1511    extract_code: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
1512    // Fn(element: TElement) -> String
1513    make_doc_description: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
1514    metadata: ErrorCodeMetadata,
1515}
1516
1517impl<TElement: Clone + Into<String>> ErrorCodeCategory<TElement> {
1518    fn new(
1519        extract_code: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
1520        make_doc_description: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
1521        metadata: Option<ErrorCodeMetadata>,
1522    ) -> Self {
1523        Self {
1524            extract_code,
1525            make_doc_description,
1526            metadata: metadata.unwrap_or_else(|| DEFAULT_METADATA.clone()),
1527        }
1528    }
1529
1530    // PORT_NOTE: The Typescript type in the JS code only has get(), but I also added createCode()
1531    // here since it's used in the return type of makeErrorCodeCategory().
1532    fn create_code(&self, element: TElement) -> ErrorCodeDefinition {
1533        ErrorCodeDefinition::new(
1534            (self.extract_code)(element.clone()),
1535            (self.make_doc_description)(element),
1536            Some(self.metadata.clone()),
1537        )
1538    }
1539}
1540
1541impl ErrorCodeCategory<String> {
1542    fn new_federation_directive(
1543        code_suffix: String,
1544        make_doc_description: Box<dyn 'static + Send + Sync + Fn(String) -> String>,
1545        metadata: Option<ErrorCodeMetadata>,
1546    ) -> Self {
1547        Self::new(
1548            Box::new(move |element: String| format!("{}_{}", element.to_uppercase(), code_suffix)),
1549            make_doc_description,
1550            metadata,
1551        )
1552    }
1553}
1554
1555static INVALID_GRAPHQL: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1556    ErrorCodeDefinition::new(
1557        "INVALID_GRAPHQL".to_owned(),
1558        "A schema is invalid GraphQL: it violates one of the rule of the specification.".to_owned(),
1559        None,
1560    )
1561});
1562static DIRECTIVE_DEFINITION_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1563    ErrorCodeDefinition::new(
1564        "DIRECTIVE_DEFINITION_INVALID".to_owned(),
1565        "A built-in or federation directive has an invalid definition in the schema.".to_owned(),
1566        Some(ErrorCodeMetadata {
1567            replaces: &["TAG_DEFINITION_INVALID"],
1568            ..DEFAULT_METADATA.clone()
1569        }),
1570    )
1571});
1572
1573static TYPE_DEFINITION_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1574    ErrorCodeDefinition::new(
1575        "TYPE_DEFINITION_INVALID".to_owned(),
1576        "A built-in or federation type has an invalid definition in the schema.".to_owned(),
1577        None,
1578    )
1579});
1580
1581static UNSUPPORTED_LINKED_FEATURE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1582    ErrorCodeDefinition::new(
1583        "UNSUPPORTED_LINKED_FEATURE".to_owned(),
1584        "Indicates that a feature used in a @link is either unsupported or is used with unsupported options.".to_owned(),
1585        None,
1586    )
1587});
1588
1589static UNKNOWN_FEDERATION_LINK_VERSION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1590    ErrorCodeDefinition::new(
1591        "UNKNOWN_FEDERATION_LINK_VERSION".to_owned(),
1592        "The version of federation in a @link directive on the schema is unknown.".to_owned(),
1593        None,
1594    )
1595});
1596
1597static UNKNOWN_LINK_VERSION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1598    ErrorCodeDefinition::new(
1599        "UNKNOWN_LINK_VERSION".to_owned(),
1600        "The version of @link set on the schema is unknown.".to_owned(),
1601        Some(ErrorCodeMetadata {
1602            added_in: "2.1.0",
1603            replaces: &[],
1604        }),
1605    )
1606});
1607
1608static FIELDS_HAS_ARGS: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
1609    ErrorCodeCategory::new_federation_directive(
1610        "FIELDS_HAS_ARGS".to_owned(),
1611        Box::new(|directive| {
1612            format!(
1613                "The `fields` argument of a `@{directive}` directive includes a field defined with arguments (which is not currently supported)."
1614            )
1615        }),
1616        None,
1617    )
1618});
1619
1620static KEY_FIELDS_HAS_ARGS: LazyLock<ErrorCodeDefinition> =
1621    LazyLock::new(|| FIELDS_HAS_ARGS.create_code("key".to_owned()));
1622
1623static PROVIDES_FIELDS_HAS_ARGS: LazyLock<ErrorCodeDefinition> =
1624    LazyLock::new(|| FIELDS_HAS_ARGS.create_code("provides".to_owned()));
1625
1626static DIRECTIVE_FIELDS_MISSING_EXTERNAL: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(
1627    || {
1628        ErrorCodeCategory::new_federation_directive(
1629            "FIELDS_MISSING_EXTERNAL".to_owned(),
1630            Box::new(|directive| {
1631                format!(
1632                    "The `fields` argument of a `@{directive}` directive includes a field that is not marked as `@external`."
1633                )
1634            }),
1635            Some(ErrorCodeMetadata {
1636                added_in: FED1_CODE,
1637                replaces: &[],
1638            }),
1639        )
1640    },
1641);
1642
1643static PROVIDES_FIELDS_MISSING_EXTERNAL: LazyLock<ErrorCodeDefinition> =
1644    LazyLock::new(|| DIRECTIVE_FIELDS_MISSING_EXTERNAL.create_code("provides".to_owned()));
1645static REQUIRES_FIELDS_MISSING_EXTERNAL: LazyLock<ErrorCodeDefinition> =
1646    LazyLock::new(|| DIRECTIVE_FIELDS_MISSING_EXTERNAL.create_code("requires".to_owned()));
1647
1648static DIRECTIVE_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeCategory<String>> =
1649    LazyLock::new(|| {
1650        ErrorCodeCategory::new_federation_directive(
1651            "UNSUPPORTED_ON_INTERFACE".to_owned(),
1652            Box::new(|directive| {
1653                let suffix = if directive == "key" {
1654                    "only supported when @linking to federation 2.3+"
1655                } else {
1656                    "not (yet) supported"
1657                };
1658                format!("A `@{directive}` directive is used on an interface, which is {suffix}.")
1659            }),
1660            None,
1661        )
1662    });
1663
1664static KEY_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeDefinition> =
1665    LazyLock::new(|| DIRECTIVE_UNSUPPORTED_ON_INTERFACE.create_code("key".to_owned()));
1666static PROVIDES_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeDefinition> =
1667    LazyLock::new(|| DIRECTIVE_UNSUPPORTED_ON_INTERFACE.create_code("provides".to_owned()));
1668static REQUIRES_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeDefinition> =
1669    LazyLock::new(|| DIRECTIVE_UNSUPPORTED_ON_INTERFACE.create_code("requires".to_owned()));
1670
1671static DIRECTIVE_IN_FIELDS_ARG: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
1672    ErrorCodeCategory::new_federation_directive(
1673        "DIRECTIVE_IN_FIELDS_ARG".to_owned(),
1674        Box::new(|directive| {
1675            format!(
1676                "The `fields` argument of a `@{directive}` directive includes some directive applications. This is not supported"
1677            )
1678        }),
1679        Some(ErrorCodeMetadata {
1680            added_in: "2.1.0",
1681            replaces: &[],
1682        }),
1683    )
1684});
1685
1686static KEY_DIRECTIVE_IN_FIELDS_ARGS: LazyLock<ErrorCodeDefinition> =
1687    LazyLock::new(|| DIRECTIVE_IN_FIELDS_ARG.create_code("key".to_owned()));
1688static PROVIDES_DIRECTIVE_IN_FIELDS_ARGS: LazyLock<ErrorCodeDefinition> =
1689    LazyLock::new(|| DIRECTIVE_IN_FIELDS_ARG.create_code("provides".to_owned()));
1690static REQUIRES_DIRECTIVE_IN_FIELDS_ARGS: LazyLock<ErrorCodeDefinition> =
1691    LazyLock::new(|| DIRECTIVE_IN_FIELDS_ARG.create_code("requires".to_owned()));
1692
1693static EXTERNAL_UNUSED: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1694    ErrorCodeDefinition::new(
1695        "EXTERNAL_UNUSED".to_owned(),
1696        "An `@external` field is not being used by any instance of `@key`, `@requires`, `@provides` or to satisfy an interface implementation.".to_owned(),
1697        Some(ErrorCodeMetadata {
1698            added_in: FED1_CODE,
1699            replaces: &[],
1700        }),
1701)
1702});
1703
1704static TYPE_WITH_ONLY_UNUSED_EXTERNAL: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1705    ErrorCodeDefinition::new(
1706        "TYPE_WITH_ONLY_UNUSED_EXTERNAL".to_owned(),
1707        [
1708            "A federation 1 schema has a composite type comprised only of unused external fields.".to_owned(),
1709            format!("Note that this error can _only_ be raised for federation 1 schema as federation 2 schema do not allow unused external fields (and errors with code {} will be raised in that case).", EXTERNAL_UNUSED.code),
1710            "But when federation 1 schema are automatically migrated to federation 2 ones, unused external fields are automatically removed, and in rare case this can leave a type empty. If that happens, an error with this code will be raised".to_owned()
1711        ].join(" "),
1712        None,
1713)
1714});
1715
1716static PROVIDES_ON_NON_OBJECT_FIELD: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1717    ErrorCodeDefinition::new(
1718        "PROVIDES_ON_NON_OBJECT_FIELD".to_owned(),
1719        "A `@provides` directive is used to mark a field whose base type is not an object type."
1720            .to_owned(),
1721        None,
1722    )
1723});
1724
1725static DIRECTIVE_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
1726    ErrorCodeCategory::new_federation_directive(
1727        "INVALID_FIELDS_TYPE".to_owned(),
1728        Box::new(|directive| {
1729            format!(
1730                "The value passed to the `fields` argument of a `@{directive}` directive is not a string."
1731            )
1732        }),
1733        None,
1734    )
1735});
1736
1737static KEY_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeDefinition> =
1738    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS_TYPE.create_code("key".to_owned()));
1739static PROVIDES_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeDefinition> =
1740    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS_TYPE.create_code("provides".to_owned()));
1741static REQUIRES_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeDefinition> =
1742    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS_TYPE.create_code("requires".to_owned()));
1743
1744static DIRECTIVE_INVALID_FIELDS: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
1745    ErrorCodeCategory::new_federation_directive(
1746        "INVALID_FIELDS".to_owned(),
1747        Box::new(|directive| {
1748            format!(
1749                "The `fields` argument of a `@{directive}` directive is invalid (it has invalid syntax, includes unknown fields, ...)."
1750            )
1751        }),
1752        None,
1753    )
1754});
1755
1756static KEY_INVALID_FIELDS: LazyLock<ErrorCodeDefinition> =
1757    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS.create_code("key".to_owned()));
1758static PROVIDES_INVALID_FIELDS: LazyLock<ErrorCodeDefinition> =
1759    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS.create_code("provides".to_owned()));
1760static REQUIRES_INVALID_FIELDS: LazyLock<ErrorCodeDefinition> =
1761    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS.create_code("requires".to_owned()));
1762
1763static KEY_FIELDS_SELECT_INVALID_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1764    ErrorCodeDefinition::new(
1765        "KEY_FIELDS_SELECT_INVALID_TYPE".to_owned(),
1766        "The `fields` argument of `@key` directive includes a field whose type is a list, interface, or union type. Fields of these types cannot be part of a `@key`".to_owned(),
1767        Some(ErrorCodeMetadata {
1768            added_in: FED1_CODE,
1769            replaces: &[],
1770        }),
1771)
1772});
1773
1774static ROOT_TYPE_USED: LazyLock<ErrorCodeCategory<SchemaRootKind>> = LazyLock::new(|| {
1775    ErrorCodeCategory::new(
1776        Box::new(|element| {
1777            let kind: String = element.into();
1778            format!("ROOT_{}_USED", kind.to_uppercase())
1779        }),
1780        Box::new(|element| {
1781            let kind: String = element.into();
1782            format!(
1783                "A subgraph's schema defines a type with the name `{kind}`, while also specifying a _different_ type name as the root query object. This is not allowed."
1784            )
1785        }),
1786        Some(ErrorCodeMetadata {
1787            added_in: FED1_CODE,
1788            replaces: &[],
1789        }),
1790    )
1791});
1792
1793static ROOT_QUERY_USED: LazyLock<ErrorCodeDefinition> =
1794    LazyLock::new(|| ROOT_TYPE_USED.create_code(SchemaRootKind::Query));
1795static ROOT_MUTATION_USED: LazyLock<ErrorCodeDefinition> =
1796    LazyLock::new(|| ROOT_TYPE_USED.create_code(SchemaRootKind::Mutation));
1797static ROOT_SUBSCRIPTION_USED: LazyLock<ErrorCodeDefinition> =
1798    LazyLock::new(|| ROOT_TYPE_USED.create_code(SchemaRootKind::Subscription));
1799
1800static INVALID_SUBGRAPH_NAME: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1801    ErrorCodeDefinition::new(
1802        "INVALID_SUBGRAPH_NAME".to_owned(),
1803        "A subgraph name is invalid (subgraph names cannot be a single underscore (\"_\"))."
1804            .to_owned(),
1805        None,
1806    )
1807});
1808
1809static NO_QUERIES: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1810    ErrorCodeDefinition::new(
1811        "NO_QUERIES".to_owned(),
1812        "None of the composed subgraphs expose any query.".to_owned(),
1813        None,
1814    )
1815});
1816
1817static INTERFACE_FIELD_NO_IMPLEM: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1818    ErrorCodeDefinition::new(
1819        "INTERFACE_FIELD_NO_IMPLEM".to_owned(),
1820        "After subgraph merging, an implementation is missing a field of one of the interface it implements (which can happen for valid subgraphs).".to_owned(),
1821        None,
1822    )
1823});
1824
1825static TYPE_KIND_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1826    ErrorCodeDefinition::new(
1827        "TYPE_KIND_MISMATCH".to_owned(),
1828        "A type has the same name in different subgraphs, but a different kind. For instance, one definition is an object type but another is an interface.".to_owned(),
1829        Some(ErrorCodeMetadata {
1830            replaces: &["VALUE_TYPE_KIND_MISMATCH", "EXTENSION_OF_WRONG_KIND", "ENUM_MISMATCH_TYPE"],
1831            ..DEFAULT_METADATA.clone()
1832        }),
1833    )
1834});
1835
1836static EXTERNAL_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1837    ErrorCodeDefinition::new(
1838        "EXTERNAL_TYPE_MISMATCH".to_owned(),
1839        "An `@external` field has a type that is incompatible with the declaration(s) of that field in other subgraphs.".to_owned(),
1840        Some(ErrorCodeMetadata {
1841            added_in: FED1_CODE,
1842            replaces: &[],
1843        }),
1844    )
1845});
1846
1847static EXTERNAL_COLLISION_WITH_ANOTHER_DIRECTIVE: LazyLock<ErrorCodeDefinition> =
1848    LazyLock::new(|| {
1849        ErrorCodeDefinition::new(
1850            "EXTERNAL_COLLISION_WITH_ANOTHER_DIRECTIVE".to_owned(),
1851            "The @external directive collides with other directives in some situations.".to_owned(),
1852            Some(ErrorCodeMetadata {
1853                added_in: "2.1.0",
1854                replaces: &[],
1855            }),
1856        )
1857    });
1858
1859static EXTERNAL_ARGUMENT_MISSING: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1860    ErrorCodeDefinition::new(
1861        "EXTERNAL_ARGUMENT_MISSING".to_owned(),
1862        "An `@external` field is missing some arguments present in the declaration(s) of that field in other subgraphs.".to_owned(),
1863        None,
1864    )
1865});
1866
1867static EXTERNAL_ARGUMENT_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1868    ErrorCodeDefinition::new(
1869        "EXTERNAL_ARGUMENT_TYPE_MISMATCH".to_owned(),
1870        "An `@external` field declares an argument with a type that is incompatible with the corresponding argument in the declaration(s) of that field in other subgraphs.".to_owned(),
1871        None,
1872    )
1873});
1874
1875static EXTERNAL_ARGUMENT_DEFAULT_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1876    ErrorCodeDefinition::new(
1877        "EXTERNAL_ARGUMENT_DEFAULT_MISMATCH".to_owned(),
1878        "An `@external` field declares an argument with a default that is incompatible with the corresponding argument in the declaration(s) of that field in other subgraphs.".to_owned(),
1879        None,
1880    )
1881});
1882
1883static EXTERNAL_ON_INTERFACE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1884    ErrorCodeDefinition::new(
1885        "EXTERNAL_ON_INTERFACE".to_owned(),
1886        "The field of an interface type is marked with `@external`: as external is about marking field not resolved by the subgraph and as interface field are not resolved (only implementations of those fields are), an \"external\" interface field is nonsensical".to_owned(),
1887        None,
1888    )
1889});
1890
1891static MERGED_DIRECTIVE_APPLICATION_ON_EXTERNAL: LazyLock<ErrorCodeDefinition> = LazyLock::new(
1892    || {
1893        ErrorCodeDefinition::new(
1894        "MERGED_DIRECTIVE_APPLICATION_ON_EXTERNAL".to_owned(),
1895        "In a subgraph, a field is both marked @external and has a merged directive applied to it".to_owned(),
1896        None,
1897    )
1898    },
1899);
1900
1901static FIELD_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1902    ErrorCodeDefinition::new(
1903        "FIELD_TYPE_MISMATCH".to_owned(),
1904        "A field has a type that is incompatible with other declarations of that field in other subgraphs.".to_owned(),
1905        Some(ErrorCodeMetadata {
1906            replaces: &["VALUE_TYPE_FIELD_TYPE_MISMATCH"],
1907            ..DEFAULT_METADATA.clone()
1908        }),
1909    )
1910});
1911
1912static FIELD_ARGUMENT_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1913    ErrorCodeDefinition::new(
1914        "FIELD_ARGUMENT_TYPE_MISMATCH".to_owned(),
1915        "An argument (of a field/directive) has a type that is incompatible with that of other declarations of that same argument in other subgraphs.".to_owned(),
1916        Some(ErrorCodeMetadata {
1917            replaces: &["VALUE_TYPE_INPUT_VALUE_MISMATCH"],
1918            ..DEFAULT_METADATA.clone()
1919        }),
1920    )
1921});
1922
1923static INPUT_FIELD_DEFAULT_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1924    ErrorCodeDefinition::new(
1925        "INPUT_FIELD_DEFAULT_MISMATCH".to_owned(),
1926        "An input field has a default value that is incompatible with other declarations of that field in other subgraphs.".to_owned(),
1927        None,
1928    )
1929});
1930
1931static FIELD_ARGUMENT_DEFAULT_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1932    ErrorCodeDefinition::new(
1933        "FIELD_ARGUMENT_DEFAULT_MISMATCH".to_owned(),
1934        "An argument (of a field/directive) has a default value that is incompatible with that of other declarations of that same argument in other subgraphs.".to_owned(),
1935        None,
1936    )
1937});
1938
1939static EXTENSION_WITH_NO_BASE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1940    ErrorCodeDefinition::new(
1941        "EXTENSION_WITH_NO_BASE".to_owned(),
1942        "A subgraph is attempting to `extend` a type that is not originally defined in any known subgraph.".to_owned(),
1943        Some(ErrorCodeMetadata {
1944            added_in: FED1_CODE,
1945            replaces: &[],
1946        }),
1947    )
1948});
1949
1950static EXTERNAL_MISSING_ON_BASE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1951    ErrorCodeDefinition::new(
1952        "EXTERNAL_MISSING_ON_BASE".to_owned(),
1953        "A field is marked as `@external` in a subgraph but with no non-external declaration in any other subgraph.".to_owned(),
1954        Some(ErrorCodeMetadata {
1955            added_in: FED1_CODE,
1956            replaces: &[],
1957        }),
1958    )
1959});
1960
1961static INVALID_FIELD_SHARING: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1962    ErrorCodeDefinition::new(
1963        "INVALID_FIELD_SHARING".to_owned(),
1964        "A field that is non-shareable in at least one subgraph is resolved by multiple subgraphs."
1965            .to_owned(),
1966        None,
1967    )
1968});
1969
1970static INVALID_SHAREABLE_USAGE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1971    ErrorCodeDefinition::new(
1972        "INVALID_SHAREABLE_USAGE".to_owned(),
1973        "The `@shareable` federation directive is used in an invalid way.".to_owned(),
1974        Some(ErrorCodeMetadata {
1975            added_in: "2.1.2",
1976            replaces: &[],
1977        }),
1978    )
1979});
1980
1981static INVALID_LINK_DIRECTIVE_USAGE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1982    ErrorCodeDefinition::new(
1983        "INVALID_LINK_DIRECTIVE_USAGE".to_owned(),
1984        "An application of the @link directive is invalid/does not respect the specification."
1985            .to_owned(),
1986        None,
1987    )
1988});
1989
1990static INVALID_LINK_IDENTIFIER: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1991    ErrorCodeDefinition::new(
1992        "INVALID_LINK_IDENTIFIER".to_owned(),
1993        "A url/version for a @link feature is invalid/does not respect the specification."
1994            .to_owned(),
1995        Some(ErrorCodeMetadata {
1996            added_in: "2.1.0",
1997            replaces: &[],
1998        }),
1999    )
2000});
2001
2002static LINK_IMPORT_NAME_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2003    ErrorCodeDefinition::new(
2004        "LINK_IMPORT_NAME_MISMATCH".to_owned(),
2005        "The import name for a merged directive (as declared by the relevant `@link(import:)` argument) is inconsistent between subgraphs.".to_owned(),
2006        None,
2007    )
2008});
2009
2010static REFERENCED_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2011    ErrorCodeDefinition::new(
2012        "REFERENCED_INACCESSIBLE".to_owned(),
2013        "An element is marked as @inaccessible but is referenced by an element visible in the API schema.".to_owned(),
2014        None,
2015    )
2016});
2017
2018static DEFAULT_VALUE_USES_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2019    ErrorCodeDefinition::new(
2020        "DEFAULT_VALUE_USES_INACCESSIBLE".to_owned(),
2021        "An element is marked as @inaccessible but is used in the default value of an element visible in the API schema.".to_owned(),
2022        None,
2023    )
2024});
2025
2026static QUERY_ROOT_TYPE_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2027    ErrorCodeDefinition::new(
2028        "QUERY_ROOT_TYPE_INACCESSIBLE".to_owned(),
2029        "An element is marked as @inaccessible but is the query root type, which must be visible in the API schema.".to_owned(),
2030        None,
2031    )
2032});
2033
2034static REQUIRED_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2035    ErrorCodeDefinition::new(
2036        "REQUIRED_INACCESSIBLE".to_owned(),
2037        "An element is marked as @inaccessible but is required by an element visible in the API schema.".to_owned(),
2038        None,
2039    )
2040});
2041
2042static IMPLEMENTED_BY_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2043    ErrorCodeDefinition::new(
2044        "IMPLEMENTED_BY_INACCESSIBLE".to_owned(),
2045        "An element is marked as @inaccessible but implements an element visible in the API schema.".to_owned(),
2046        None,
2047    )
2048});
2049
2050static DISALLOWED_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2051    ErrorCodeDefinition::new(
2052        "DISALLOWED_INACCESSIBLE".to_owned(),
2053        "An element is marked as @inaccessible that is not allowed to be @inaccessible.".to_owned(),
2054        None,
2055    )
2056});
2057
2058static ONLY_INACCESSIBLE_CHILDREN: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2059    ErrorCodeDefinition::new(
2060        "ONLY_INACCESSIBLE_CHILDREN".to_owned(),
2061        "A type visible in the API schema has only @inaccessible children.".to_owned(),
2062        None,
2063    )
2064});
2065
2066static REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2067    || {
2068        ErrorCodeDefinition::new(
2069        "REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH".to_owned(),
2070        "A field of an input object type is mandatory in some subgraphs, but the field is not defined in all the subgraphs that define the input object type.".to_owned(),
2071        None,
2072    )
2073    },
2074);
2075
2076static REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2077    || {
2078        ErrorCodeDefinition::new(
2079        "REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH".to_owned(),
2080        "An argument of a field or directive definition is mandatory in some subgraphs, but the argument is not defined in all the subgraphs that define the field or directive definition.".to_owned(),
2081        None,
2082    )
2083    },
2084);
2085
2086static EMPTY_MERGED_INPUT_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2087    ErrorCodeDefinition::new(
2088        "EMPTY_MERGED_INPUT_TYPE".to_owned(),
2089        "An input object type has no field common to all the subgraphs that define the type. Merging that type would result in an invalid empty input object type.".to_owned(),
2090        None,
2091    )
2092});
2093
2094static INPUT_FIELD_MERGE_FAILED: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2095    ErrorCodeDefinition::new(
2096        "INPUT_FIELD_MERGE_FAILED".to_owned(),
2097        "Failed to merge an input object field due to incompatible definitions across subgraphs."
2098            .to_owned(),
2099        None,
2100    )
2101});
2102
2103static ENUM_VALUE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2104    ErrorCodeDefinition::new(
2105        "ENUM_VALUE_MISMATCH".to_owned(),
2106        "An enum type that is used as both an input and output type has a value that is not defined in all the subgraphs that define the enum type.".to_owned(),
2107        None,
2108    )
2109});
2110
2111static EMPTY_MERGED_ENUM_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2112    ErrorCodeDefinition::new(
2113        "EMPTY_MERGED_ENUM_TYPE".to_owned(),
2114        "An enum type has no value common to all the subgraphs that define the type. Merging that type would result in an invalid empty enum type.".to_owned(),
2115        None,
2116    )
2117});
2118
2119static SHAREABLE_HAS_MISMATCHED_RUNTIME_TYPES: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2120    || {
2121        ErrorCodeDefinition::new(
2122        "SHAREABLE_HAS_MISMATCHED_RUNTIME_TYPES".to_owned(),
2123        "A shareable field return type has mismatched possible runtime types in the subgraphs in which the field is declared. As shared fields must resolve the same way in all subgraphs, this is almost surely a mistake.".to_owned(),
2124        None,
2125    )
2126    },
2127);
2128
2129static SATISFIABILITY_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2130    ErrorCodeDefinition::new(
2131        "SATISFIABILITY_ERROR".to_owned(),
2132        "Subgraphs can be merged, but the resulting supergraph API would have queries that cannot be satisfied by those subgraphs.".to_owned(),
2133        None,
2134    )
2135});
2136
2137static MAX_VALIDATION_SUBGRAPH_PATHS_EXCEEDED: LazyLock<ErrorCodeDefinition> =
2138    LazyLock::new(|| {
2139        ErrorCodeDefinition::new(
2140            "MAX_VALIDATION_SUBGRAPH_PATHS_EXCEEDED".to_owned(),
2141            "The maximum number of validation subgraph paths has been exceeded.".to_owned(),
2142            Some(ErrorCodeMetadata {
2143                added_in: "2.8.0",
2144                replaces: &[],
2145            }),
2146        )
2147    });
2148
2149static OVERRIDE_FROM_SELF_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2150    ErrorCodeDefinition::new(
2151        "OVERRIDE_FROM_SELF_ERROR".to_owned(),
2152        "Field with `@override` directive has \"from\" location that references its own subgraph."
2153            .to_owned(),
2154        None,
2155    )
2156});
2157
2158static OVERRIDE_SOURCE_HAS_OVERRIDE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2159    ErrorCodeDefinition::new(
2160        "OVERRIDE_SOURCE_HAS_OVERRIDE".to_owned(),
2161        "Field which is overridden to another subgraph is also marked @override.".to_owned(),
2162        None,
2163    )
2164});
2165
2166static OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2167    || {
2168        ErrorCodeDefinition::new(
2169        "OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE".to_owned(),
2170        "The @override directive cannot be used on external fields, nor to override fields with either @external, @provides, or @requires.".to_owned(),
2171        None,
2172    )
2173    },
2174);
2175
2176static OVERRIDE_ON_INTERFACE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2177    ErrorCodeDefinition::new(
2178        "OVERRIDE_ON_INTERFACE".to_owned(),
2179        "The @override directive cannot be used on the fields of an interface type.".to_owned(),
2180        Some(ErrorCodeMetadata {
2181            added_in: "2.3.0",
2182            replaces: &[],
2183        }),
2184    )
2185});
2186
2187static OVERRIDE_LABEL_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2188    ErrorCodeDefinition::new(
2189        "OVERRIDE_LABEL_INVALID".to_owned(),
2190        r#"The @override directive `label` argument must match the pattern /^[a-zA-Z][a-zA-Z0-9_\-:./]*$/ or /^percent\((\d{1,2}(\.\d{1,8})?|100)\)$/"#.to_owned(),
2191        Some(ErrorCodeMetadata {
2192            added_in: "2.7.0",
2193            replaces: &[],
2194        }),
2195    )
2196});
2197
2198static UNSUPPORTED_FEATURE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2199    ErrorCodeDefinition::new(
2200        "UNSUPPORTED_FEATURE".to_owned(),
2201        "Indicates an error due to feature currently unsupported by federation.".to_owned(),
2202        Some(ErrorCodeMetadata {
2203            added_in: "2.1.0",
2204            replaces: &[],
2205        }),
2206    )
2207});
2208
2209static INVALID_FEDERATION_SUPERGRAPH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2210    ErrorCodeDefinition::new(
2211        "INVALID_FEDERATION_SUPERGRAPH".to_owned(),
2212        "Indicates that a schema provided for an Apollo Federation supergraph is not a valid supergraph schema.".to_owned(),
2213        Some(ErrorCodeMetadata {
2214            added_in: "2.1.0",
2215            replaces: &[],
2216        }),
2217    )
2218});
2219
2220static DOWNSTREAM_SERVICE_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2221    ErrorCodeDefinition::new(
2222        "DOWNSTREAM_SERVICE_ERROR".to_owned(),
2223        "Indicates an error in a subgraph service query during query execution in a federated service.".to_owned(),
2224        Some(ErrorCodeMetadata {
2225            added_in: FED1_CODE,
2226            replaces: &[],
2227        }),
2228    )
2229});
2230
2231static DIRECTIVE_COMPOSITION_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2232    ErrorCodeDefinition::new(
2233        "DIRECTIVE_COMPOSITION_ERROR".to_owned(),
2234        "Error when composing custom directives.".to_owned(),
2235        Some(ErrorCodeMetadata {
2236            added_in: "2.1.0",
2237            replaces: &[],
2238        }),
2239    )
2240});
2241
2242static INTERFACE_OBJECT_USAGE_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2243    ErrorCodeDefinition::new(
2244        "INTERFACE_OBJECT_USAGE_ERROR".to_owned(),
2245        "Error in the usage of the @interfaceObject directive.".to_owned(),
2246        Some(ErrorCodeMetadata {
2247            added_in: "2.3.0",
2248            replaces: &[],
2249        }),
2250    )
2251});
2252
2253static INTERFACE_KEY_NOT_ON_IMPLEMENTATION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2254    ErrorCodeDefinition::new(
2255        "INTERFACE_KEY_NOT_ON_IMPLEMENTATION".to_owned(),
2256        "A `@key` is defined on an interface type, but is not defined (or is not resolvable) on at least one of the interface implementations".to_owned(),
2257        Some(ErrorCodeMetadata {
2258            added_in: "2.3.0",
2259            replaces: &[],
2260        }),
2261    )
2262});
2263
2264static INTERFACE_KEY_MISSING_IMPLEMENTATION_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2265    || {
2266        ErrorCodeDefinition::new(
2267        "INTERFACE_KEY_MISSING_IMPLEMENTATION_TYPE".to_owned(),
2268        "A subgraph has a `@key` on an interface type, but that subgraph does not define an implementation (in the supergraph) of that interface".to_owned(),
2269        Some(ErrorCodeMetadata {
2270            added_in: "2.3.0",
2271            replaces: &[],
2272        }),
2273    )
2274    },
2275);
2276
2277static INTERNAL: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2278    ErrorCodeDefinition::new(
2279        "INTERNAL".to_owned(),
2280        "An internal federation error occured.".to_owned(),
2281        None,
2282    )
2283});
2284
2285static ERROR_CODE_MISSING: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2286    ErrorCodeDefinition::new(
2287        "ERROR_CODE_MISSING".to_owned(),
2288        "An internal federation error occurred when translating a federation error into an error code".to_owned(),
2289        None,
2290    )
2291});
2292
2293static UNSUPPORTED_FEDERATION_VERSION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2294    ErrorCodeDefinition::new(
2295        "UNSUPPORTED_FEDERATION_VERSION".to_owned(),
2296        "Supergraphs composed with federation version 1 are not supported. Please recompose your supergraph with federation version 2 or greater".to_owned(),
2297        None,
2298    )
2299});
2300
2301static UNSUPPORTED_FEDERATION_DIRECTIVE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2302    ErrorCodeDefinition::new(
2303        "UNSUPPORTED_FEDERATION_DIRECTIVE".to_owned(),
2304        "Indicates that the specified specification version is outside of supported range"
2305            .to_owned(),
2306        None,
2307    )
2308});
2309
2310static QUERY_PLAN_COMPLEXITY_EXCEEDED: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2311    ErrorCodeDefinition::new(
2312        "QUERY_PLAN_COMPLEXITY_EXCEEDED".to_owned(),
2313        "Indicates that provided query has too many possible ways to generate a plan and cannot be planned in a reasonable amount of time"
2314            .to_owned(),
2315        None,
2316    )
2317});
2318
2319static NO_PLAN_FOUND_WITH_DISABLED_SUBGRAPHS: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2320    ErrorCodeDefinition::new(
2321        "NO_PLAN_FOUND_WITH_DISABLED_SUBGRAPHS".to_owned(),
2322        "Indicates that the provided query could not be query planned due to subgraphs being disabled"
2323            .to_owned(),
2324        None,
2325    )
2326});
2327
2328static COST_APPLIED_TO_INTERFACE_FIELD: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2329    ErrorCodeDefinition::new(
2330        "COST_APPLIED_TO_INTERFACE_FIELD".to_owned(),
2331        "The `@cost` directive must be applied to concrete types".to_owned(),
2332        Some(ErrorCodeMetadata {
2333            added_in: "2.9.2",
2334            replaces: &[],
2335        }),
2336    )
2337});
2338
2339static LIST_SIZE_APPLIED_TO_NON_LIST: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2340    ErrorCodeDefinition::new(
2341        "LIST_SIZE_APPLIED_TO_NON_LIST".to_owned(),
2342        "The `@listSize` directive must be applied to list types".to_owned(),
2343        Some(ErrorCodeMetadata {
2344            added_in: "2.9.2",
2345            replaces: &[],
2346        }),
2347    )
2348});
2349
2350static LIST_SIZE_INVALID_ASSUMED_SIZE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2351    ErrorCodeDefinition::new(
2352        "LIST_SIZE_INVALID_ASSUMED_SIZE".to_owned(),
2353        "The `@listSize` directive assumed size cannot be negative".to_owned(),
2354        Some(ErrorCodeMetadata {
2355            added_in: "2.9.2",
2356            replaces: &[],
2357        }),
2358    )
2359});
2360
2361static LIST_SIZE_INVALID_SLICING_ARGUMENT: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2362    ErrorCodeDefinition::new(
2363        "LIST_SIZE_INVALID_SLICING_ARGUMENT".to_owned(),
2364        "The `@listSize` directive must have existing integer slicing arguments".to_owned(),
2365        Some(ErrorCodeMetadata {
2366            added_in: "2.9.2",
2367            replaces: &[],
2368        }),
2369    )
2370});
2371
2372static LIST_SIZE_INVALID_SIZED_FIELD: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2373    ErrorCodeDefinition::new(
2374        "LIST_SIZE_INVALID_SIZED_FIELD".to_owned(),
2375        "The `@listSize` directive must reference existing list fields as sized fields".to_owned(),
2376        Some(ErrorCodeMetadata {
2377            added_in: "2.9.2",
2378            replaces: &[],
2379        }),
2380    )
2381});
2382
2383static CONTEXT_NAME_CONTAINS_UNDERSCORE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2384    ErrorCodeDefinition::new(
2385        "CONTEXT_NAME_CONTAINS_UNDERSCORE".to_owned(),
2386        "Context name is invalid.".to_owned(),
2387        Some(ErrorCodeMetadata {
2388            added_in: "2.8.0",
2389            replaces: &[],
2390        }),
2391    )
2392});
2393
2394static CONTEXT_NAME_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2395    ErrorCodeDefinition::new(
2396        "CONTEXT_NAME_INVALID".to_owned(),
2397        "Context name is invalid.".to_owned(),
2398        Some(ErrorCodeMetadata {
2399            added_in: "2.8.0",
2400            replaces: &[],
2401        }),
2402    )
2403});
2404
2405static CONTEXT_NOT_SET: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2406    ErrorCodeDefinition::new(
2407        "CONTEXT_NOT_SET".to_owned(),
2408        "Context is never set for context trying to be used".to_owned(),
2409        Some(ErrorCodeMetadata {
2410            added_in: "2.8.0",
2411            replaces: &[],
2412        }),
2413    )
2414});
2415
2416static NO_CONTEXT_REFERENCED: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2417    ErrorCodeDefinition::new(
2418        "NO_CONTEXT_REFERENCED".to_owned(),
2419        "Selection in @fromContext field argument does not reference a context".to_owned(),
2420        Some(ErrorCodeMetadata {
2421            added_in: "2.8.0",
2422            replaces: &[],
2423        }),
2424    )
2425});
2426
2427static NO_SELECTION_FOR_CONTEXT: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2428    ErrorCodeDefinition::new(
2429        "NO_SELECTION_FOR_CONTEXT".to_owned(),
2430        "field parameter in @fromContext must contain a selection set".to_owned(),
2431        Some(ErrorCodeMetadata {
2432            added_in: "2.8.0",
2433            replaces: &[],
2434        }),
2435    )
2436});
2437
2438static CONTEXT_NO_RESOLVABLE_KEY: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2439    ErrorCodeDefinition::new(
2440        "CONTEXT_NO_RESOLVABLE_KEY".to_owned(),
2441        "If an ObjectType uses a @fromContext, at least one of its keys must be resolvable"
2442            .to_owned(),
2443        Some(ErrorCodeMetadata {
2444            added_in: "2.8.0",
2445            replaces: &[],
2446        }),
2447    )
2448});
2449
2450static CONTEXT_SELECTION_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2451    ErrorCodeDefinition::new(
2452        "CONTEXT_SELECTION_INVALID".to_owned(),
2453        "The selection set is invalid".to_owned(),
2454        Some(ErrorCodeMetadata {
2455            added_in: "2.8.0",
2456            replaces: &[],
2457        }),
2458    )
2459});
2460
2461static INVALID_TAG_NAME: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2462    ErrorCodeDefinition::new(
2463        "INVALID_TAG_NAME".to_owned(),
2464        "Invalid value for argument \"name\" in application of @tag.".to_owned(),
2465        Some(ErrorCodeMetadata {
2466            added_in: "2.0.0",
2467            replaces: &[],
2468        }),
2469    )
2470});
2471
2472static CACHE_TAG_INVALID_FORMAT: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2473    ErrorCodeDefinition::new(
2474        "CACHE_TAG_INVALID_FORMAT".to_owned(),
2475        "Invalid format string in @cacheTag directive.".to_owned(),
2476        Some(ErrorCodeMetadata {
2477            added_in: "2.12.0",
2478            replaces: &[],
2479        }),
2480    )
2481});
2482
2483static CACHE_TAG_APPLIED_TO_NON_ROOT_FIELD: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2484    ErrorCodeDefinition::new(
2485        "CACHE_TAG_APPLIED_TO_NON_ROOT_FIELD".to_owned(),
2486        "@cacheTag on a field can only be applied on root fields.".to_owned(),
2487        Some(ErrorCodeMetadata {
2488            added_in: "2.12.0",
2489            replaces: &[],
2490        }),
2491    )
2492});
2493
2494static CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ROOT_FIELD: LazyLock<ErrorCodeDefinition> =
2495    LazyLock::new(|| {
2496        ErrorCodeDefinition::new(
2497            "CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ROOT_FIELD".to_owned(),
2498            "@cacheTag on root fields can only reference arguments using $args in format."
2499                .to_owned(),
2500            Some(ErrorCodeMetadata {
2501                added_in: "2.12.0",
2502                replaces: &[],
2503            }),
2504        )
2505    });
2506
2507static CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ENTITY: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2508    || {
2509        ErrorCodeDefinition::new(
2510            "CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ENTITY".to_owned(),
2511            "cacheTag applied on types can only reference arguments in format using $key, and each referenced field must be a member of every @key field set.".to_owned(),
2512            Some(ErrorCodeMetadata {
2513                added_in: "2.12.0",
2514                replaces: &[],
2515            }),
2516        )
2517    },
2518);
2519
2520static CACHE_TAG_ENTITY_NOT_RESOLVABLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2521    ErrorCodeDefinition::new(
2522        "CACHE_TAG_ENTITY_NOT_RESOLVABLE".to_owned(),
2523        "@cacheTag can only apply on resolvable entities (object with at least one @key directive)."
2524            .to_owned(),
2525        Some(ErrorCodeMetadata {
2526            added_in: "2.12.0",
2527            replaces: &[],
2528        }),
2529    )
2530});
2531
2532static CONTEXTUAL_ARGUMENT_NOT_CONTEXTUAL_IN_ALL_SUBGRAPHS: LazyLock<ErrorCodeDefinition> =
2533    LazyLock::new(|| {
2534        ErrorCodeDefinition::new(
2535            "CONTEXTUAL_ARGUMENT_NOT_CONTEXTUAL_IN_ALL_SUBGRAPHS".to_owned(),
2536            "Argument on field is marked contextual in only some subgraphs".to_owned(),
2537            Some(ErrorCodeMetadata {
2538                added_in: "2.7.0",
2539                replaces: &[],
2540            }),
2541        )
2542    });
2543
2544static QUERY_ROOT_MISSING: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2545    ErrorCodeDefinition::new(
2546        "QUERY_ROOT_MISSING".to_owned(),
2547        "The schema has no query root type.".to_owned(),
2548        Some(ErrorCodeMetadata {
2549            added_in: "2.0.0",
2550            replaces: &[],
2551        }),
2552    )
2553});
2554
2555static AUTH_REQUIREMENTS_APPLIED_ON_INTERFACE: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2556    || {
2557        ErrorCodeDefinition::new(
2558        "AUTH_REQUIREMENTS_APPLIED_ON_INTERFACE".to_owned(),
2559        "The @authenticated, @requiresScopes and @policy directive cannot be applied on interface, interface object or their fields.".to_owned(),
2560        Some(ErrorCodeMetadata {
2561            added_in: "2.9.4",
2562            replaces: &[],
2563        }),
2564    )
2565    },
2566);
2567
2568static MISSING_TRANSITIVE_AUTH_REQUIREMENTS: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2569    ErrorCodeDefinition::new(
2570            "MISSING_TRANSITIVE_AUTH_REQUIREMENTS".to_owned(),
2571            "Field missing transitive @authenticated, @requiresScopes and/or @policy auth requirements needed to access dependent data.".to_owned(),
2572            Some(ErrorCodeMetadata {
2573                added_in: "2.9.4",
2574                replaces: &[],
2575            }),
2576        )
2577});
2578
2579#[derive(Debug, PartialEq, strum_macros::EnumIter)]
2580pub enum ErrorCode {
2581    ErrorCodeMissing,
2582    Internal,
2583    ExtensionWithNoBase,
2584    InvalidGraphQL,
2585    DirectiveDefinitionInvalid,
2586    TypeDefinitionInvalid,
2587    UnsupportedLinkedFeature,
2588    UnknownFederationLinkVersion,
2589    UnknownLinkVersion,
2590    KeyFieldsHasArgs,
2591    ProvidesFieldsHasArgs,
2592    ProvidesFieldsMissingExternal,
2593    RequiresFieldsMissingExternal,
2594    KeyUnsupportedOnInterface,
2595    ProvidesUnsupportedOnInterface,
2596    RequiresUnsupportedOnInterface,
2597    KeyDirectiveInFieldsArgs,
2598    ProvidesDirectiveInFieldsArgs,
2599    RequiresDirectiveInFieldsArgs,
2600    ExternalUnused,
2601    TypeWithOnlyUnusedExternal,
2602    ProvidesOnNonObjectField,
2603    KeyInvalidFieldsType,
2604    ProvidesInvalidFieldsType,
2605    RequiresInvalidFieldsType,
2606    KeyInvalidFields,
2607    ProvidesInvalidFields,
2608    RequiresInvalidFields,
2609    KeyFieldsSelectInvalidType,
2610    RootQueryUsed,
2611    RootMutationUsed,
2612    RootSubscriptionUsed,
2613    InvalidSubgraphName,
2614    NoQueries,
2615    InterfaceFieldNoImplem,
2616    TypeKindMismatch,
2617    ExternalTypeMismatch,
2618    ExternalCollisionWithAnotherDirective,
2619    ExternalArgumentMissing,
2620    ExternalArgumentTypeMismatch,
2621    ExternalArgumentDefaultMismatch,
2622    ExternalOnInterface,
2623    MergedDirectiveApplicationOnExternal,
2624    FieldTypeMismatch,
2625    FieldArgumentTypeMismatch,
2626    InputFieldDefaultMismatch,
2627    FieldArgumentDefaultMismatch,
2628    ExternalMissingOnBase,
2629    InvalidFieldSharing,
2630    InvalidShareableUsage,
2631    InvalidLinkDirectiveUsage,
2632    InvalidLinkIdentifier,
2633    LinkImportNameMismatch,
2634    ReferencedInaccessible,
2635    DefaultValueUsesInaccessible,
2636    QueryRootTypeInaccessible,
2637    RequiredInaccessible,
2638    ImplementedByInaccessible,
2639    DisallowedInaccessible,
2640    OnlyInaccessibleChildren,
2641    RequiredInputFieldMissingInSomeSubgraph,
2642    RequiredArgumentMissingInSomeSubgraph,
2643    EmptyMergedInputType,
2644    InputFieldMergeFailed,
2645    EnumValueMismatch,
2646    EmptyMergedEnumType,
2647    ShareableHasMismatchedRuntimeTypes,
2648    SatisfiabilityError,
2649    MaxValidationSubgraphPathsExceeded,
2650    OverrideFromSelfError,
2651    OverrideSourceHasOverride,
2652    OverrideCollisionWithAnotherDirective,
2653    OverrideOnInterface,
2654    UnsupportedFeature,
2655    InvalidFederationSupergraph,
2656    DownstreamServiceError,
2657    DirectiveCompositionError,
2658    InterfaceObjectUsageError,
2659    InterfaceKeyNotOnImplementation,
2660    InterfaceKeyMissingImplementationType,
2661    UnsupportedFederationVersion,
2662    UnsupportedFederationDirective,
2663    QueryPlanComplexityExceededError,
2664    NoPlanFoundWithDisabledSubgraphs,
2665    CostAppliedToInterfaceField,
2666    ListSizeAppliedToNonList,
2667    ListSizeInvalidAssumedSize,
2668    ListSizeInvalidSlicingArgument,
2669    ListSizeInvalidSizedField,
2670    ContextNameInvalid,
2671    ContextNameContainsUnderscore,
2672    ContextNotSet,
2673    NoContextReferenced,
2674    NoSelectionForContext,
2675    ContextNoResolvableKey,
2676    ContextSelectionInvalid,
2677    InvalidTagName,
2678    CacheTagInvalidFormat,
2679    CacheTagAppliedToNonRootField,
2680    CacheTagInvalidFormatArgumentOnRootField,
2681    CacheTagInvalidFormatArgumentOnEntity,
2682    CacheTagEntityNotResolvable,
2683    OverrideLabelInvalid,
2684    ContextualArgumentNotContextualInAllSubgraphs,
2685    QueryRootMissing,
2686    AuthRequirementsAppliedOnInterface,
2687    MissingTransitiveAuthRequirements,
2688}
2689
2690impl ErrorCode {
2691    pub fn definition(&self) -> &'static ErrorCodeDefinition {
2692        match self {
2693            ErrorCode::Internal => &INTERNAL,
2694            ErrorCode::ExtensionWithNoBase => &EXTENSION_WITH_NO_BASE,
2695            ErrorCode::InvalidGraphQL => &INVALID_GRAPHQL,
2696            ErrorCode::DirectiveDefinitionInvalid => &DIRECTIVE_DEFINITION_INVALID,
2697            ErrorCode::TypeDefinitionInvalid => &TYPE_DEFINITION_INVALID,
2698            ErrorCode::UnsupportedLinkedFeature => &UNSUPPORTED_LINKED_FEATURE,
2699            ErrorCode::UnknownFederationLinkVersion => &UNKNOWN_FEDERATION_LINK_VERSION,
2700            ErrorCode::UnknownLinkVersion => &UNKNOWN_LINK_VERSION,
2701            ErrorCode::KeyFieldsHasArgs => &KEY_FIELDS_HAS_ARGS,
2702            ErrorCode::ProvidesFieldsHasArgs => &PROVIDES_FIELDS_HAS_ARGS,
2703            ErrorCode::ProvidesFieldsMissingExternal => &PROVIDES_FIELDS_MISSING_EXTERNAL,
2704            ErrorCode::RequiresFieldsMissingExternal => &REQUIRES_FIELDS_MISSING_EXTERNAL,
2705            ErrorCode::KeyUnsupportedOnInterface => &KEY_UNSUPPORTED_ON_INTERFACE,
2706            ErrorCode::ProvidesUnsupportedOnInterface => &PROVIDES_UNSUPPORTED_ON_INTERFACE,
2707            ErrorCode::RequiresUnsupportedOnInterface => &REQUIRES_UNSUPPORTED_ON_INTERFACE,
2708            ErrorCode::KeyDirectiveInFieldsArgs => &KEY_DIRECTIVE_IN_FIELDS_ARGS,
2709            ErrorCode::ProvidesDirectiveInFieldsArgs => &PROVIDES_DIRECTIVE_IN_FIELDS_ARGS,
2710            ErrorCode::RequiresDirectiveInFieldsArgs => &REQUIRES_DIRECTIVE_IN_FIELDS_ARGS,
2711            ErrorCode::ExternalUnused => &EXTERNAL_UNUSED,
2712            ErrorCode::ExternalCollisionWithAnotherDirective => {
2713                &EXTERNAL_COLLISION_WITH_ANOTHER_DIRECTIVE
2714            }
2715            ErrorCode::TypeWithOnlyUnusedExternal => &TYPE_WITH_ONLY_UNUSED_EXTERNAL,
2716            ErrorCode::ProvidesOnNonObjectField => &PROVIDES_ON_NON_OBJECT_FIELD,
2717            ErrorCode::KeyInvalidFieldsType => &KEY_INVALID_FIELDS_TYPE,
2718            ErrorCode::ProvidesInvalidFieldsType => &PROVIDES_INVALID_FIELDS_TYPE,
2719            ErrorCode::RequiresInvalidFieldsType => &REQUIRES_INVALID_FIELDS_TYPE,
2720            ErrorCode::KeyInvalidFields => &KEY_INVALID_FIELDS,
2721            ErrorCode::ProvidesInvalidFields => &PROVIDES_INVALID_FIELDS,
2722            ErrorCode::RequiresInvalidFields => &REQUIRES_INVALID_FIELDS,
2723            ErrorCode::KeyFieldsSelectInvalidType => &KEY_FIELDS_SELECT_INVALID_TYPE,
2724            ErrorCode::RootQueryUsed => &ROOT_QUERY_USED,
2725            ErrorCode::RootMutationUsed => &ROOT_MUTATION_USED,
2726            ErrorCode::RootSubscriptionUsed => &ROOT_SUBSCRIPTION_USED,
2727            ErrorCode::InvalidSubgraphName => &INVALID_SUBGRAPH_NAME,
2728            ErrorCode::NoQueries => &NO_QUERIES,
2729            ErrorCode::InterfaceFieldNoImplem => &INTERFACE_FIELD_NO_IMPLEM,
2730            ErrorCode::TypeKindMismatch => &TYPE_KIND_MISMATCH,
2731            ErrorCode::ExternalTypeMismatch => &EXTERNAL_TYPE_MISMATCH,
2732            ErrorCode::ExternalArgumentMissing => &EXTERNAL_ARGUMENT_MISSING,
2733            ErrorCode::ExternalArgumentTypeMismatch => &EXTERNAL_ARGUMENT_TYPE_MISMATCH,
2734            ErrorCode::ExternalArgumentDefaultMismatch => &EXTERNAL_ARGUMENT_DEFAULT_MISMATCH,
2735            ErrorCode::ExternalOnInterface => &EXTERNAL_ON_INTERFACE,
2736            ErrorCode::MergedDirectiveApplicationOnExternal => {
2737                &MERGED_DIRECTIVE_APPLICATION_ON_EXTERNAL
2738            }
2739            ErrorCode::FieldTypeMismatch => &FIELD_TYPE_MISMATCH,
2740            ErrorCode::FieldArgumentTypeMismatch => &FIELD_ARGUMENT_TYPE_MISMATCH,
2741            ErrorCode::InputFieldDefaultMismatch => &INPUT_FIELD_DEFAULT_MISMATCH,
2742            ErrorCode::FieldArgumentDefaultMismatch => &FIELD_ARGUMENT_DEFAULT_MISMATCH,
2743            ErrorCode::ExternalMissingOnBase => &EXTERNAL_MISSING_ON_BASE,
2744            ErrorCode::InvalidFieldSharing => &INVALID_FIELD_SHARING,
2745            ErrorCode::InvalidShareableUsage => &INVALID_SHAREABLE_USAGE,
2746            ErrorCode::InvalidLinkDirectiveUsage => &INVALID_LINK_DIRECTIVE_USAGE,
2747            ErrorCode::InvalidLinkIdentifier => &INVALID_LINK_IDENTIFIER,
2748            ErrorCode::LinkImportNameMismatch => &LINK_IMPORT_NAME_MISMATCH,
2749            ErrorCode::ReferencedInaccessible => &REFERENCED_INACCESSIBLE,
2750            ErrorCode::DefaultValueUsesInaccessible => &DEFAULT_VALUE_USES_INACCESSIBLE,
2751            ErrorCode::QueryRootTypeInaccessible => &QUERY_ROOT_TYPE_INACCESSIBLE,
2752            ErrorCode::RequiredInaccessible => &REQUIRED_INACCESSIBLE,
2753            ErrorCode::ImplementedByInaccessible => &IMPLEMENTED_BY_INACCESSIBLE,
2754            ErrorCode::DisallowedInaccessible => &DISALLOWED_INACCESSIBLE,
2755            ErrorCode::OnlyInaccessibleChildren => &ONLY_INACCESSIBLE_CHILDREN,
2756            ErrorCode::RequiredInputFieldMissingInSomeSubgraph => {
2757                &REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH
2758            }
2759            ErrorCode::RequiredArgumentMissingInSomeSubgraph => {
2760                &REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH
2761            }
2762            ErrorCode::EmptyMergedInputType => &EMPTY_MERGED_INPUT_TYPE,
2763            ErrorCode::InputFieldMergeFailed => &INPUT_FIELD_MERGE_FAILED,
2764            ErrorCode::EnumValueMismatch => &ENUM_VALUE_MISMATCH,
2765            ErrorCode::EmptyMergedEnumType => &EMPTY_MERGED_ENUM_TYPE,
2766            ErrorCode::ShareableHasMismatchedRuntimeTypes => {
2767                &SHAREABLE_HAS_MISMATCHED_RUNTIME_TYPES
2768            }
2769            ErrorCode::SatisfiabilityError => &SATISFIABILITY_ERROR,
2770            ErrorCode::MaxValidationSubgraphPathsExceeded => {
2771                &MAX_VALIDATION_SUBGRAPH_PATHS_EXCEEDED
2772            }
2773            ErrorCode::OverrideFromSelfError => &OVERRIDE_FROM_SELF_ERROR,
2774            ErrorCode::OverrideSourceHasOverride => &OVERRIDE_SOURCE_HAS_OVERRIDE,
2775            ErrorCode::OverrideCollisionWithAnotherDirective => {
2776                &OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE
2777            }
2778            ErrorCode::OverrideOnInterface => &OVERRIDE_ON_INTERFACE,
2779            ErrorCode::UnsupportedFeature => &UNSUPPORTED_FEATURE,
2780            ErrorCode::InvalidFederationSupergraph => &INVALID_FEDERATION_SUPERGRAPH,
2781            ErrorCode::DownstreamServiceError => &DOWNSTREAM_SERVICE_ERROR,
2782            ErrorCode::DirectiveCompositionError => &DIRECTIVE_COMPOSITION_ERROR,
2783            ErrorCode::InterfaceObjectUsageError => &INTERFACE_OBJECT_USAGE_ERROR,
2784            ErrorCode::InterfaceKeyNotOnImplementation => &INTERFACE_KEY_NOT_ON_IMPLEMENTATION,
2785            ErrorCode::InterfaceKeyMissingImplementationType => {
2786                &INTERFACE_KEY_MISSING_IMPLEMENTATION_TYPE
2787            }
2788            ErrorCode::UnsupportedFederationVersion => &UNSUPPORTED_FEDERATION_VERSION,
2789            ErrorCode::UnsupportedFederationDirective => &UNSUPPORTED_FEDERATION_DIRECTIVE,
2790            ErrorCode::QueryPlanComplexityExceededError => &QUERY_PLAN_COMPLEXITY_EXCEEDED,
2791            ErrorCode::NoPlanFoundWithDisabledSubgraphs => &NO_PLAN_FOUND_WITH_DISABLED_SUBGRAPHS,
2792            ErrorCode::CostAppliedToInterfaceField => &COST_APPLIED_TO_INTERFACE_FIELD,
2793            ErrorCode::ListSizeAppliedToNonList => &LIST_SIZE_APPLIED_TO_NON_LIST,
2794            ErrorCode::ListSizeInvalidAssumedSize => &LIST_SIZE_INVALID_ASSUMED_SIZE,
2795            ErrorCode::ListSizeInvalidSlicingArgument => &LIST_SIZE_INVALID_SLICING_ARGUMENT,
2796            ErrorCode::ListSizeInvalidSizedField => &LIST_SIZE_INVALID_SIZED_FIELD,
2797            ErrorCode::ContextNameContainsUnderscore => &CONTEXT_NAME_CONTAINS_UNDERSCORE,
2798            ErrorCode::ContextNameInvalid => &CONTEXT_NAME_INVALID,
2799            ErrorCode::ContextNotSet => &CONTEXT_NOT_SET,
2800            ErrorCode::NoContextReferenced => &NO_CONTEXT_REFERENCED,
2801            ErrorCode::NoSelectionForContext => &NO_SELECTION_FOR_CONTEXT,
2802            ErrorCode::ContextNoResolvableKey => &CONTEXT_NO_RESOLVABLE_KEY,
2803            ErrorCode::ContextSelectionInvalid => &CONTEXT_SELECTION_INVALID,
2804            ErrorCode::InvalidTagName => &INVALID_TAG_NAME,
2805            ErrorCode::CacheTagInvalidFormat => &CACHE_TAG_INVALID_FORMAT,
2806            ErrorCode::CacheTagAppliedToNonRootField => &CACHE_TAG_APPLIED_TO_NON_ROOT_FIELD,
2807            ErrorCode::CacheTagInvalidFormatArgumentOnRootField => {
2808                &CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ROOT_FIELD
2809            }
2810            ErrorCode::CacheTagInvalidFormatArgumentOnEntity => {
2811                &CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ENTITY
2812            }
2813            ErrorCode::CacheTagEntityNotResolvable => &CACHE_TAG_ENTITY_NOT_RESOLVABLE,
2814            ErrorCode::ErrorCodeMissing => &ERROR_CODE_MISSING,
2815            ErrorCode::OverrideLabelInvalid => &OVERRIDE_LABEL_INVALID,
2816            ErrorCode::ContextualArgumentNotContextualInAllSubgraphs => {
2817                &CONTEXTUAL_ARGUMENT_NOT_CONTEXTUAL_IN_ALL_SUBGRAPHS
2818            }
2819            ErrorCode::QueryRootMissing => &QUERY_ROOT_MISSING,
2820            ErrorCode::AuthRequirementsAppliedOnInterface => {
2821                &AUTH_REQUIREMENTS_APPLIED_ON_INTERFACE
2822            }
2823            ErrorCode::MissingTransitiveAuthRequirements => &MISSING_TRANSITIVE_AUTH_REQUIREMENTS,
2824        }
2825    }
2826}