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("{message}")]
871    QueryPlanComplexityExceeded { message: String },
872    #[error("the caller requested cancellation")]
873    PlanningCancelled,
874    #[error("No plan was found when subgraphs were disabled")]
875    NoPlanFoundWithDisabledSubgraphs,
876    #[error("Context name \"{name}\" may not contain an underscore.")]
877    ContextNameContainsUnderscore { name: String },
878    #[error("Context name \"{name}\" is invalid. It should have only alphanumeric characters.")]
879    ContextNameInvalid { name: String },
880    #[error("{message}")]
881    ContextNotSet { message: String },
882    #[error("{message}")]
883    NoContextReferenced { message: String },
884    #[error("{message}")]
885    NoSelectionForContext { message: String },
886    #[error("{message}")]
887    ContextNoResolvableKey { message: String },
888    #[error("@cost cannot be applied to interface \"{interface}.{field}\"")]
889    CostAppliedToInterfaceField { interface: Name, field: Name },
890    #[error("{message}")]
891    ContextSelectionInvalid { message: String },
892    #[error("{message}")]
893    ListSizeAppliedToNonList { message: String },
894    #[error("{message}")]
895    ListSizeInvalidAssumedSize { message: String },
896    #[error("{message}")]
897    ListSizeInvalidSlicingArgument { message: String },
898    #[error("{message}")]
899    ListSizeInvalidSizedField { message: String },
900    #[error("{message}")]
901    InvalidTagName { message: String },
902    /// `@cacheTag` directive validation errors (subgraph)
903    #[error("cacheTag format is invalid: {message}")]
904    CacheTagInvalidFormat { message: String },
905    #[error(
906        "error on field \"{field_name}\" on type \"{type_name}\": cacheTag can only apply on root fields or entity types"
907    )]
908    CacheTagAppliedToNonRootField { type_name: Name, field_name: Name },
909    #[error("cacheTag applied on root fields can only reference arguments in format using $args")]
910    CacheTagInvalidFormatArgumentOnRootField,
911    #[error("cacheTag applied on types can only reference arguments in format using $key")]
912    CacheTagInvalidFormatArgumentOnEntity { type_name: Name, format: String },
913    #[error(
914        "Object \"{0}\" is not an entity. cacheTag can only apply on resolvable entities, object containing at least 1 @key directive and resolvable"
915    )]
916    CacheTagEntityNotResolvable(Name),
917    #[error("{message}")]
918    QueryRootMissing { message: String },
919    #[error(
920        "Invalid use of @{directive_name} on {kind} \"{coordinate}\": @{directive_name} cannot be applied on interfaces, interface fields and interface objects"
921    )]
922    AuthRequirementsAppliedOnInterface {
923        directive_name: String,
924        kind: String,
925        coordinate: String,
926    },
927    #[error("{message}")]
928    MissingTransitiveAuthRequirements { message: String },
929}
930
931impl SingleFederationError {
932    pub fn code(&self) -> ErrorCode {
933        match self {
934            SingleFederationError::Internal { .. } => ErrorCode::Internal,
935            SingleFederationError::InternalRebaseError { .. } => ErrorCode::Internal,
936            SingleFederationError::InternalUnmergeableFields { .. } => ErrorCode::Internal,
937            SingleFederationError::InvalidGraphQL { .. }
938            | SingleFederationError::InvalidGraphQLName(_) => ErrorCode::InvalidGraphQL,
939            SingleFederationError::InvalidSubgraph { .. } => ErrorCode::InvalidGraphQL,
940            // Technically it's not invalid graphql, but it is invalid syntax inside graphql...
941            SingleFederationError::FromContextParseError { .. } => ErrorCode::InvalidGraphQL,
942            // TODO(@goto-bus-stop): this should have a different error code: it's not invalid,
943            // just unsupported due to internal limitations.
944            SingleFederationError::UnsupportedSpreadDirective { .. } => ErrorCode::InvalidGraphQL,
945            // TODO(@goto-bus-stop): this should have a different error code: it's not the graphql
946            // that's invalid, but the operation name
947            SingleFederationError::UnknownOperation => ErrorCode::InvalidGraphQL,
948            SingleFederationError::OperationNameNotProvided => ErrorCode::InvalidGraphQL,
949            SingleFederationError::DirectiveDefinitionInvalid { .. } => {
950                ErrorCode::DirectiveDefinitionInvalid
951            }
952            SingleFederationError::TypeDefinitionInvalid { .. } => ErrorCode::TypeDefinitionInvalid,
953            SingleFederationError::UnsupportedFederationDirective { .. } => {
954                ErrorCode::UnsupportedFederationDirective
955            }
956            SingleFederationError::UnsupportedFederationVersion { .. } => {
957                ErrorCode::UnsupportedFederationVersion
958            }
959            SingleFederationError::UnsupportedLinkedFeature { .. } => {
960                ErrorCode::UnsupportedLinkedFeature
961            }
962            SingleFederationError::UnknownFederationLinkVersion { .. } => {
963                ErrorCode::UnknownFederationLinkVersion
964            }
965            SingleFederationError::UnknownLinkVersion { .. } => ErrorCode::UnknownLinkVersion,
966            SingleFederationError::KeyFieldsHasArgs { .. } => ErrorCode::KeyFieldsHasArgs,
967            SingleFederationError::ProvidesFieldsHasArgs { .. } => ErrorCode::ProvidesFieldsHasArgs,
968            SingleFederationError::ProvidesFieldsMissingExternal { .. } => {
969                ErrorCode::ProvidesFieldsMissingExternal
970            }
971            SingleFederationError::RequiresFieldsMissingExternal { .. } => {
972                ErrorCode::RequiresFieldsMissingExternal
973            }
974            SingleFederationError::KeyUnsupportedOnInterface { .. } => {
975                ErrorCode::KeyUnsupportedOnInterface
976            }
977            SingleFederationError::ProvidesUnsupportedOnInterface { .. } => {
978                ErrorCode::ProvidesUnsupportedOnInterface
979            }
980            SingleFederationError::RequiresUnsupportedOnInterface { .. } => {
981                ErrorCode::RequiresUnsupportedOnInterface
982            }
983            SingleFederationError::KeyHasDirectiveInFieldsArg { .. } => {
984                ErrorCode::KeyDirectiveInFieldsArgs
985            }
986            SingleFederationError::ProvidesHasDirectiveInFieldsArg { .. } => {
987                ErrorCode::ProvidesDirectiveInFieldsArgs
988            }
989            SingleFederationError::RequiresHasDirectiveInFieldsArg { .. } => {
990                ErrorCode::RequiresDirectiveInFieldsArgs
991            }
992            SingleFederationError::ExternalUnused { .. } => ErrorCode::ExternalUnused,
993            SingleFederationError::TypeWithOnlyUnusedExternal { .. } => {
994                ErrorCode::TypeWithOnlyUnusedExternal
995            }
996            SingleFederationError::ProvidesOnNonObjectField { .. } => {
997                ErrorCode::ProvidesOnNonObjectField
998            }
999            SingleFederationError::KeyInvalidFieldsType { .. } => ErrorCode::KeyInvalidFieldsType,
1000            SingleFederationError::ProvidesInvalidFieldsType { .. } => {
1001                ErrorCode::ProvidesInvalidFieldsType
1002            }
1003            SingleFederationError::RequiresInvalidFieldsType { .. } => {
1004                ErrorCode::RequiresInvalidFieldsType
1005            }
1006            SingleFederationError::KeyInvalidFields { .. } => ErrorCode::KeyInvalidFields,
1007            SingleFederationError::ProvidesInvalidFields { .. } => ErrorCode::ProvidesInvalidFields,
1008            SingleFederationError::RequiresInvalidFields { .. } => ErrorCode::RequiresInvalidFields,
1009            SingleFederationError::KeyFieldsSelectInvalidType { .. } => {
1010                ErrorCode::KeyFieldsSelectInvalidType
1011            }
1012            SingleFederationError::RootQueryUsed { .. } => ErrorCode::RootQueryUsed,
1013            SingleFederationError::RootMutationUsed { .. } => ErrorCode::RootMutationUsed,
1014            SingleFederationError::RootSubscriptionUsed { .. } => ErrorCode::RootSubscriptionUsed,
1015            SingleFederationError::InvalidSubgraphName { .. } => ErrorCode::InvalidSubgraphName,
1016            SingleFederationError::NoQueries { .. } => ErrorCode::NoQueries,
1017            SingleFederationError::InterfaceFieldNoImplem { .. } => {
1018                ErrorCode::InterfaceFieldNoImplem
1019            }
1020            SingleFederationError::ExternalTypeMismatch { .. } => ErrorCode::ExternalTypeMismatch,
1021            SingleFederationError::ExternalCollisionWithAnotherDirective { .. } => {
1022                ErrorCode::ExternalCollisionWithAnotherDirective
1023            }
1024            SingleFederationError::ExternalArgumentMissing { .. } => {
1025                ErrorCode::ExternalArgumentMissing
1026            }
1027            SingleFederationError::ExternalArgumentTypeMismatch { .. } => {
1028                ErrorCode::ExternalArgumentTypeMismatch
1029            }
1030            SingleFederationError::ExternalArgumentDefaultMismatch { .. } => {
1031                ErrorCode::ExternalArgumentDefaultMismatch
1032            }
1033            SingleFederationError::ExternalOnInterface { .. } => ErrorCode::ExternalOnInterface,
1034            SingleFederationError::MergedDirectiveApplicationOnExternal { .. } => {
1035                ErrorCode::MergedDirectiveApplicationOnExternal
1036            }
1037            SingleFederationError::FieldTypeMismatch { .. } => ErrorCode::FieldTypeMismatch,
1038            SingleFederationError::FieldArgumentTypeMismatch { .. } => {
1039                ErrorCode::FieldArgumentTypeMismatch
1040            }
1041            SingleFederationError::InputFieldDefaultMismatch { .. } => {
1042                ErrorCode::InputFieldDefaultMismatch
1043            }
1044            SingleFederationError::FieldArgumentDefaultMismatch { .. } => {
1045                ErrorCode::FieldArgumentDefaultMismatch
1046            }
1047            SingleFederationError::ExtensionWithNoBase { .. } => ErrorCode::ExtensionWithNoBase,
1048            SingleFederationError::ExternalMissingOnBase { .. } => ErrorCode::ExternalMissingOnBase,
1049            SingleFederationError::InvalidFieldSharing { .. } => ErrorCode::InvalidFieldSharing,
1050            SingleFederationError::InvalidShareableUsage { .. } => ErrorCode::InvalidShareableUsage,
1051            SingleFederationError::InvalidLinkDirectiveUsage { .. } => {
1052                ErrorCode::InvalidLinkDirectiveUsage
1053            }
1054            SingleFederationError::InvalidLinkIdentifier { .. } => ErrorCode::InvalidLinkIdentifier,
1055            SingleFederationError::ReferencedInaccessible { .. } => {
1056                ErrorCode::ReferencedInaccessible
1057            }
1058            SingleFederationError::DefaultValueUsesInaccessible { .. } => {
1059                ErrorCode::DefaultValueUsesInaccessible
1060            }
1061            SingleFederationError::QueryRootTypeInaccessible { .. } => {
1062                ErrorCode::QueryRootTypeInaccessible
1063            }
1064            SingleFederationError::RequiredInaccessible { .. } => ErrorCode::RequiredInaccessible,
1065            SingleFederationError::ImplementedByInaccessible { .. } => {
1066                ErrorCode::ImplementedByInaccessible
1067            }
1068            SingleFederationError::DisallowedInaccessible { .. } => {
1069                ErrorCode::DisallowedInaccessible
1070            }
1071            SingleFederationError::OnlyInaccessibleChildren { .. } => {
1072                ErrorCode::OnlyInaccessibleChildren
1073            }
1074            SingleFederationError::RequiredInputFieldMissingInSomeSubgraph { .. } => {
1075                ErrorCode::RequiredInputFieldMissingInSomeSubgraph
1076            }
1077            SingleFederationError::RequiredArgumentMissingInSomeSubgraph { .. } => {
1078                ErrorCode::RequiredArgumentMissingInSomeSubgraph
1079            }
1080            SingleFederationError::EmptyMergedInputType { .. } => ErrorCode::EmptyMergedInputType,
1081            SingleFederationError::EnumValueMismatch { .. } => ErrorCode::EnumValueMismatch,
1082            SingleFederationError::EmptyMergedEnumType { .. } => ErrorCode::EmptyMergedEnumType,
1083            SingleFederationError::ShareableHasMismatchedRuntimeTypes { .. } => {
1084                ErrorCode::ShareableHasMismatchedRuntimeTypes
1085            }
1086            SingleFederationError::SatisfiabilityError { .. } => ErrorCode::SatisfiabilityError,
1087            SingleFederationError::OverrideFromSelfError { .. } => ErrorCode::OverrideFromSelfError,
1088            SingleFederationError::OverrideSourceHasOverride { .. } => {
1089                ErrorCode::OverrideSourceHasOverride
1090            }
1091            SingleFederationError::OverrideCollisionWithAnotherDirective { .. } => {
1092                ErrorCode::OverrideCollisionWithAnotherDirective
1093            }
1094            SingleFederationError::OverrideOnInterface { .. } => ErrorCode::OverrideOnInterface,
1095            SingleFederationError::UnsupportedFeature { .. } => ErrorCode::UnsupportedFeature,
1096            SingleFederationError::InvalidFederationSupergraph { .. } => {
1097                ErrorCode::InvalidFederationSupergraph
1098            }
1099            SingleFederationError::DownstreamServiceError { .. } => {
1100                ErrorCode::DownstreamServiceError
1101            }
1102            SingleFederationError::DirectiveCompositionError { .. } => {
1103                ErrorCode::DirectiveCompositionError
1104            }
1105            SingleFederationError::InterfaceObjectUsageError { .. } => {
1106                ErrorCode::InterfaceObjectUsageError
1107            }
1108            SingleFederationError::InterfaceKeyNotOnImplementation { .. } => {
1109                ErrorCode::InterfaceKeyNotOnImplementation
1110            }
1111            SingleFederationError::InterfaceKeyMissingImplementationType { .. } => {
1112                ErrorCode::InterfaceKeyMissingImplementationType
1113            }
1114            SingleFederationError::DeferredSubscriptionUnsupported => ErrorCode::Internal,
1115            SingleFederationError::QueryPlanComplexityExceeded { .. } => {
1116                ErrorCode::QueryPlanComplexityExceededError
1117            }
1118            SingleFederationError::PlanningCancelled => ErrorCode::Internal,
1119            SingleFederationError::NoPlanFoundWithDisabledSubgraphs => {
1120                ErrorCode::NoPlanFoundWithDisabledSubgraphs
1121            }
1122            SingleFederationError::ContextNameContainsUnderscore { .. } => {
1123                ErrorCode::ContextNameContainsUnderscore
1124            }
1125            SingleFederationError::ContextNameInvalid { .. } => ErrorCode::ContextNameInvalid,
1126            SingleFederationError::ContextNotSet { .. } => ErrorCode::ContextNotSet,
1127            SingleFederationError::NoContextReferenced { .. } => ErrorCode::NoContextReferenced,
1128            SingleFederationError::NoSelectionForContext { .. } => ErrorCode::NoSelectionForContext,
1129            SingleFederationError::ContextNoResolvableKey { .. } => {
1130                ErrorCode::ContextNoResolvableKey
1131            }
1132            SingleFederationError::ContextSelectionInvalid { .. } => {
1133                ErrorCode::ContextSelectionInvalid
1134            }
1135            SingleFederationError::CostAppliedToInterfaceField { .. } => {
1136                ErrorCode::CostAppliedToInterfaceField
1137            }
1138            SingleFederationError::ListSizeAppliedToNonList { .. } => {
1139                ErrorCode::ListSizeAppliedToNonList
1140            }
1141            SingleFederationError::ListSizeInvalidAssumedSize { .. } => {
1142                ErrorCode::ListSizeInvalidAssumedSize
1143            }
1144            SingleFederationError::ListSizeInvalidSlicingArgument { .. } => {
1145                ErrorCode::ListSizeInvalidSlicingArgument
1146            }
1147            SingleFederationError::ListSizeInvalidSizedField { .. } => {
1148                ErrorCode::ListSizeInvalidSizedField
1149            }
1150            #[allow(unused)]
1151            SingleFederationError::InvalidFieldSharing { .. } => ErrorCode::InvalidFieldSharing,
1152            SingleFederationError::InvalidTagName { .. } => ErrorCode::InvalidTagName,
1153            SingleFederationError::CacheTagInvalidFormat { .. } => ErrorCode::CacheTagInvalidFormat,
1154            SingleFederationError::CacheTagAppliedToNonRootField { .. } => {
1155                ErrorCode::CacheTagAppliedToNonRootField
1156            }
1157            SingleFederationError::CacheTagInvalidFormatArgumentOnRootField => {
1158                ErrorCode::CacheTagInvalidFormatArgumentOnRootField
1159            }
1160            SingleFederationError::CacheTagInvalidFormatArgumentOnEntity { .. } => {
1161                ErrorCode::CacheTagInvalidFormatArgumentOnEntity
1162            }
1163            SingleFederationError::CacheTagEntityNotResolvable { .. } => {
1164                ErrorCode::CacheTagEntityNotResolvable
1165            }
1166            SingleFederationError::QueryRootMissing { .. } => ErrorCode::QueryRootMissing,
1167            SingleFederationError::AuthRequirementsAppliedOnInterface { .. } => {
1168                ErrorCode::AuthRequirementsAppliedOnInterface
1169            }
1170            SingleFederationError::MissingTransitiveAuthRequirements { .. } => {
1171                ErrorCode::MissingTransitiveAuthRequirements
1172            }
1173        }
1174    }
1175
1176    pub fn code_string(&self) -> String {
1177        self.code().definition().code().to_string()
1178    }
1179
1180    pub(crate) fn root_already_used(
1181        operation_type: OperationType,
1182        expected_name: Name,
1183        found_name: Name,
1184    ) -> Self {
1185        match operation_type {
1186            OperationType::Query => Self::RootQueryUsed {
1187                expected_name,
1188                found_name,
1189            },
1190            OperationType::Mutation => Self::RootMutationUsed {
1191                expected_name,
1192                found_name,
1193            },
1194            OperationType::Subscription => Self::RootSubscriptionUsed {
1195                expected_name,
1196                found_name,
1197            },
1198        }
1199    }
1200}
1201
1202impl From<InvalidNameError> for FederationError {
1203    fn from(err: InvalidNameError) -> Self {
1204        SingleFederationError::from(err).into()
1205    }
1206}
1207
1208impl From<FederationSpecError> for FederationError {
1209    fn from(err: FederationSpecError) -> Self {
1210        // TODO: When we get around to finishing the composition port, we should really switch it to
1211        // using FederationError instead of FederationSpecError.
1212        let message = err.to_string();
1213        match err {
1214            FederationSpecError::UnsupportedVersionError { .. } => {
1215                SingleFederationError::UnsupportedFederationVersion { message }.into()
1216            }
1217            FederationSpecError::UnsupportedFederationDirective { .. } => {
1218                SingleFederationError::UnsupportedFederationDirective { message }.into()
1219            }
1220            FederationSpecError::InvalidGraphQLName(message) => message.into(),
1221        }
1222    }
1223}
1224
1225#[derive(Debug, Clone, thiserror::Error, Default)]
1226pub struct MultipleFederationErrors {
1227    pub(crate) errors: Vec<SingleFederationError>,
1228}
1229
1230impl MultipleFederationErrors {
1231    pub fn new() -> Self {
1232        Self { errors: vec![] }
1233    }
1234
1235    pub fn push(&mut self, error: FederationError) {
1236        match error {
1237            FederationError::SingleFederationError(error) => {
1238                self.errors.push(error);
1239            }
1240            FederationError::MultipleFederationErrors(errors) => {
1241                self.errors.extend(errors.errors);
1242            }
1243            FederationError::AggregateFederationError(errors) => {
1244                self.errors.extend(errors.causes);
1245            }
1246        }
1247    }
1248
1249    pub(crate) fn and_try(mut self, other: Result<(), FederationError>) -> Self {
1250        match other {
1251            Ok(_) => self,
1252            Err(e) => {
1253                self.push(e);
1254                self
1255            }
1256        }
1257    }
1258}
1259
1260impl Display for MultipleFederationErrors {
1261    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1262        write!(f, "The following errors occurred:")?;
1263        for error in &self.errors {
1264            write!(f, "\n  - ")?;
1265            for c in error.to_string().chars() {
1266                if c == '\n' {
1267                    write!(f, "\n    ")?;
1268                } else {
1269                    f.write_char(c)?;
1270                }
1271            }
1272        }
1273        Ok(())
1274    }
1275}
1276
1277impl FromIterator<SingleFederationError> for MultipleFederationErrors {
1278    fn from_iter<T: IntoIterator<Item = SingleFederationError>>(iter: T) -> Self {
1279        Self {
1280            errors: iter.into_iter().collect(),
1281        }
1282    }
1283}
1284
1285#[derive(Debug, Clone, thiserror::Error)]
1286pub struct AggregateFederationError {
1287    pub code: String,
1288    pub message: String,
1289    pub causes: Vec<SingleFederationError>,
1290}
1291
1292impl Display for AggregateFederationError {
1293    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1294        write!(f, "[{}] {}\nCaused by:", self.code, self.message)?;
1295        for error in &self.causes {
1296            write!(f, "\n\n  - ")?;
1297            for c in error.to_string().chars() {
1298                if c == '\n' {
1299                    write!(f, "\n    ")?;
1300                } else {
1301                    f.write_char(c)?;
1302                }
1303            }
1304        }
1305        Ok(())
1306    }
1307}
1308
1309// PORT_NOTE: Often times, JS functions would either throw/return a GraphQLError, return a vector
1310// of GraphQLErrors, or take a vector of GraphQLErrors and group them together under an
1311// AggregateGraphQLError which itself would have a specific error message and code, and throw that.
1312// We represent all these cases with an enum, and delegate to the members.
1313#[derive(Clone, thiserror::Error)]
1314pub enum FederationError {
1315    #[error(transparent)]
1316    SingleFederationError(#[from] SingleFederationError),
1317    #[error(transparent)]
1318    MultipleFederationErrors(#[from] MultipleFederationErrors),
1319    #[error(transparent)]
1320    AggregateFederationError(#[from] AggregateFederationError),
1321}
1322
1323impl std::fmt::Debug for FederationError {
1324    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1325        match self {
1326            Self::SingleFederationError(inner) => std::fmt::Debug::fmt(inner, f),
1327            Self::MultipleFederationErrors(inner) => std::fmt::Debug::fmt(inner, f),
1328            Self::AggregateFederationError(inner) => std::fmt::Debug::fmt(inner, f),
1329        }
1330    }
1331}
1332
1333impl From<DiagnosticList> for FederationError {
1334    fn from(value: DiagnosticList) -> Self {
1335        let errors: Vec<_> = value
1336            .iter()
1337            .map(|d| SingleFederationError::InvalidGraphQL {
1338                message: d.to_string(),
1339            })
1340            .collect();
1341        match errors.len().cmp(&1) {
1342            Ordering::Less => internal_error!("diagnostic list is unexpectedly empty"),
1343            Ordering::Equal => errors[0].clone().into(),
1344            Ordering::Greater => MultipleFederationErrors { errors }.into(),
1345        }
1346    }
1347}
1348
1349impl<T> From<WithErrors<T>> for FederationError {
1350    fn from(value: WithErrors<T>) -> Self {
1351        value.errors.into()
1352    }
1353}
1354
1355// Used for when we condition on a type `T: TryInto<U>`, but we have an infallible conversion of
1356// `T: Into<U>`. This allows us to unwrap the `Result<U, Infallible>` with `?`.
1357impl From<std::convert::Infallible> for FederationError {
1358    fn from(_: std::convert::Infallible) -> Self {
1359        unreachable!("Infallible should never be converted to FederationError")
1360    }
1361}
1362
1363impl FederationError {
1364    pub fn internal(message: impl Into<String>) -> Self {
1365        SingleFederationError::Internal {
1366            message: message.into(),
1367        }
1368        .into()
1369    }
1370
1371    pub fn merge(self, other: Self) -> Self {
1372        let mut result = MultipleFederationErrors::new();
1373        result.push(self);
1374        result.push(other);
1375        result.into()
1376    }
1377
1378    pub fn into_errors(self) -> Vec<SingleFederationError> {
1379        match self {
1380            FederationError::SingleFederationError(e) => vec![e],
1381            FederationError::MultipleFederationErrors(e) => e.errors,
1382            FederationError::AggregateFederationError(e) => e.causes,
1383        }
1384    }
1385
1386    pub fn errors(&self) -> Vec<&SingleFederationError> {
1387        match self {
1388            FederationError::SingleFederationError(e) => vec![e],
1389            FederationError::MultipleFederationErrors(e) => e.errors.iter().collect(),
1390            FederationError::AggregateFederationError(e) => e.causes.iter().collect(),
1391        }
1392    }
1393
1394    pub fn has_invalid_graphql_error(&self) -> bool {
1395        self.errors()
1396            .into_iter()
1397            .any(|e| matches!(e, SingleFederationError::InvalidGraphQL { .. }))
1398    }
1399}
1400
1401// Similar to `multi_try` crate, but with `FederationError` instead of `Vec<E>`.
1402pub trait MultiTry<U> {
1403    type Output;
1404
1405    fn and_try(self, other: Result<U, FederationError>) -> Self::Output;
1406}
1407
1408impl<U> MultiTry<U> for Result<(), FederationError> {
1409    type Output = Result<U, FederationError>;
1410
1411    fn and_try(self, other: Result<U, FederationError>) -> Result<U, FederationError> {
1412        match (self, other) {
1413            (Ok(_a), Ok(b)) => Ok(b),
1414            (Ok(_a), Err(b)) => Err(b),
1415            (Err(a), Ok(_b)) => Err(a),
1416            (Err(a), Err(b)) => Err(a.merge(b)),
1417        }
1418    }
1419}
1420
1421pub trait MultiTryAll: Sized + Iterator {
1422    /// Apply `predicate` on all elements of the iterator, collecting all errors (if any).
1423    /// - Returns Ok(()), if all elements are Ok.
1424    /// - Otherwise, returns a FederationError with all errors.
1425    /// - Note: Not to be confused with `try_for_each`, which stops on the first error.
1426    fn try_for_all<F>(self, mut predicate: F) -> Result<(), FederationError>
1427    where
1428        F: FnMut(Self::Item) -> Result<(), FederationError>,
1429    {
1430        let mut errors = MultipleFederationErrors::new();
1431        for item in self {
1432            match predicate(item) {
1433                Ok(()) => {}
1434                Err(e) => errors.push(e),
1435            }
1436        }
1437        errors.into_result()
1438    }
1439}
1440
1441impl<I: Iterator> MultiTryAll for I {}
1442
1443impl MultipleFederationErrors {
1444    /// Converts into `Result<(), FederationError>`.
1445    /// - The return value can be either Ok, Err with a SingleFederationError or MultipleFederationErrors,
1446    ///   depending on the number of errors in the input.
1447    pub fn into_result(self) -> Result<(), FederationError> {
1448        match self.errors.len().cmp(&1) {
1449            Ordering::Less => Ok(()),
1450            Ordering::Equal => Err(self.errors[0].clone().into()),
1451            Ordering::Greater => Err(self.into()),
1452        }
1453    }
1454}
1455
1456// We didn't track errors addition precisely pre-2.0 and tracking it now has an unclear ROI, so we
1457// just mark all the error code that predates 2.0 as 0.x.
1458const FED1_CODE: &str = "0.x";
1459
1460#[derive(Debug, Clone)]
1461pub struct ErrorCodeMetadata {
1462    pub added_in: &'static str,
1463    pub replaces: &'static [&'static str],
1464}
1465
1466#[derive(Debug)]
1467pub struct ErrorCodeDefinition {
1468    code: String,
1469    // PORT_NOTE: Known as "description" in the JS code. The name was changed to distinguish it from
1470    // Error.description().
1471    doc_description: String,
1472    metadata: ErrorCodeMetadata,
1473}
1474
1475impl ErrorCodeDefinition {
1476    fn new(code: String, doc_description: String, metadata: Option<ErrorCodeMetadata>) -> Self {
1477        Self {
1478            code,
1479            doc_description,
1480            metadata: metadata.unwrap_or_else(|| DEFAULT_METADATA.clone()),
1481        }
1482    }
1483
1484    pub fn code(&self) -> &str {
1485        &self.code
1486    }
1487
1488    pub fn doc_description(&self) -> &str {
1489        &self.doc_description
1490    }
1491
1492    pub fn metadata(&self) -> &ErrorCodeMetadata {
1493        &self.metadata
1494    }
1495}
1496
1497/*
1498 * Most codes currently originate from the initial fed 2 release so we use this for convenience.
1499 * This can be changed later, inline versions everywhere, if that becomes irrelevant.
1500 */
1501static DEFAULT_METADATA: ErrorCodeMetadata = ErrorCodeMetadata {
1502    added_in: "2.0.0",
1503    replaces: &[],
1504};
1505
1506struct ErrorCodeCategory<TElement: Clone + Into<String>> {
1507    // Fn(element: TElement) -> String
1508    extract_code: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
1509    // Fn(element: TElement) -> String
1510    make_doc_description: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
1511    metadata: ErrorCodeMetadata,
1512}
1513
1514impl<TElement: Clone + Into<String>> ErrorCodeCategory<TElement> {
1515    fn new(
1516        extract_code: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
1517        make_doc_description: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
1518        metadata: Option<ErrorCodeMetadata>,
1519    ) -> Self {
1520        Self {
1521            extract_code,
1522            make_doc_description,
1523            metadata: metadata.unwrap_or_else(|| DEFAULT_METADATA.clone()),
1524        }
1525    }
1526
1527    // PORT_NOTE: The Typescript type in the JS code only has get(), but I also added createCode()
1528    // here since it's used in the return type of makeErrorCodeCategory().
1529    fn create_code(&self, element: TElement) -> ErrorCodeDefinition {
1530        ErrorCodeDefinition::new(
1531            (self.extract_code)(element.clone()),
1532            (self.make_doc_description)(element),
1533            Some(self.metadata.clone()),
1534        )
1535    }
1536}
1537
1538impl ErrorCodeCategory<String> {
1539    fn new_federation_directive(
1540        code_suffix: String,
1541        make_doc_description: Box<dyn 'static + Send + Sync + Fn(String) -> String>,
1542        metadata: Option<ErrorCodeMetadata>,
1543    ) -> Self {
1544        Self::new(
1545            Box::new(move |element: String| format!("{}_{}", element.to_uppercase(), code_suffix)),
1546            make_doc_description,
1547            metadata,
1548        )
1549    }
1550}
1551
1552static INVALID_GRAPHQL: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1553    ErrorCodeDefinition::new(
1554        "INVALID_GRAPHQL".to_owned(),
1555        "A schema is invalid GraphQL: it violates one of the rule of the specification.".to_owned(),
1556        None,
1557    )
1558});
1559static DIRECTIVE_DEFINITION_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1560    ErrorCodeDefinition::new(
1561        "DIRECTIVE_DEFINITION_INVALID".to_owned(),
1562        "A built-in or federation directive has an invalid definition in the schema.".to_owned(),
1563        Some(ErrorCodeMetadata {
1564            replaces: &["TAG_DEFINITION_INVALID"],
1565            ..DEFAULT_METADATA.clone()
1566        }),
1567    )
1568});
1569
1570static TYPE_DEFINITION_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1571    ErrorCodeDefinition::new(
1572        "TYPE_DEFINITION_INVALID".to_owned(),
1573        "A built-in or federation type has an invalid definition in the schema.".to_owned(),
1574        None,
1575    )
1576});
1577
1578static UNSUPPORTED_LINKED_FEATURE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1579    ErrorCodeDefinition::new(
1580        "UNSUPPORTED_LINKED_FEATURE".to_owned(),
1581        "Indicates that a feature used in a @link is either unsupported or is used with unsupported options.".to_owned(),
1582        None,
1583    )
1584});
1585
1586static UNKNOWN_FEDERATION_LINK_VERSION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1587    ErrorCodeDefinition::new(
1588        "UNKNOWN_FEDERATION_LINK_VERSION".to_owned(),
1589        "The version of federation in a @link directive on the schema is unknown.".to_owned(),
1590        None,
1591    )
1592});
1593
1594static UNKNOWN_LINK_VERSION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1595    ErrorCodeDefinition::new(
1596        "UNKNOWN_LINK_VERSION".to_owned(),
1597        "The version of @link set on the schema is unknown.".to_owned(),
1598        Some(ErrorCodeMetadata {
1599            added_in: "2.1.0",
1600            replaces: &[],
1601        }),
1602    )
1603});
1604
1605static FIELDS_HAS_ARGS: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
1606    ErrorCodeCategory::new_federation_directive(
1607        "FIELDS_HAS_ARGS".to_owned(),
1608        Box::new(|directive| {
1609            format!(
1610                "The `fields` argument of a `@{directive}` directive includes a field defined with arguments (which is not currently supported)."
1611            )
1612        }),
1613        None,
1614    )
1615});
1616
1617static KEY_FIELDS_HAS_ARGS: LazyLock<ErrorCodeDefinition> =
1618    LazyLock::new(|| FIELDS_HAS_ARGS.create_code("key".to_owned()));
1619
1620static PROVIDES_FIELDS_HAS_ARGS: LazyLock<ErrorCodeDefinition> =
1621    LazyLock::new(|| FIELDS_HAS_ARGS.create_code("provides".to_owned()));
1622
1623static DIRECTIVE_FIELDS_MISSING_EXTERNAL: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(
1624    || {
1625        ErrorCodeCategory::new_federation_directive(
1626            "FIELDS_MISSING_EXTERNAL".to_owned(),
1627            Box::new(|directive| {
1628                format!(
1629                    "The `fields` argument of a `@{directive}` directive includes a field that is not marked as `@external`."
1630                )
1631            }),
1632            Some(ErrorCodeMetadata {
1633                added_in: FED1_CODE,
1634                replaces: &[],
1635            }),
1636        )
1637    },
1638);
1639
1640static PROVIDES_FIELDS_MISSING_EXTERNAL: LazyLock<ErrorCodeDefinition> =
1641    LazyLock::new(|| DIRECTIVE_FIELDS_MISSING_EXTERNAL.create_code("provides".to_owned()));
1642static REQUIRES_FIELDS_MISSING_EXTERNAL: LazyLock<ErrorCodeDefinition> =
1643    LazyLock::new(|| DIRECTIVE_FIELDS_MISSING_EXTERNAL.create_code("requires".to_owned()));
1644
1645static DIRECTIVE_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeCategory<String>> =
1646    LazyLock::new(|| {
1647        ErrorCodeCategory::new_federation_directive(
1648            "UNSUPPORTED_ON_INTERFACE".to_owned(),
1649            Box::new(|directive| {
1650                let suffix = if directive == "key" {
1651                    "only supported when @linking to federation 2.3+"
1652                } else {
1653                    "not (yet) supported"
1654                };
1655                format!("A `@{directive}` directive is used on an interface, which is {suffix}.")
1656            }),
1657            None,
1658        )
1659    });
1660
1661static KEY_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeDefinition> =
1662    LazyLock::new(|| DIRECTIVE_UNSUPPORTED_ON_INTERFACE.create_code("key".to_owned()));
1663static PROVIDES_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeDefinition> =
1664    LazyLock::new(|| DIRECTIVE_UNSUPPORTED_ON_INTERFACE.create_code("provides".to_owned()));
1665static REQUIRES_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeDefinition> =
1666    LazyLock::new(|| DIRECTIVE_UNSUPPORTED_ON_INTERFACE.create_code("requires".to_owned()));
1667
1668static DIRECTIVE_IN_FIELDS_ARG: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
1669    ErrorCodeCategory::new_federation_directive(
1670        "DIRECTIVE_IN_FIELDS_ARG".to_owned(),
1671        Box::new(|directive| {
1672            format!(
1673                "The `fields` argument of a `@{directive}` directive includes some directive applications. This is not supported"
1674            )
1675        }),
1676        Some(ErrorCodeMetadata {
1677            added_in: "2.1.0",
1678            replaces: &[],
1679        }),
1680    )
1681});
1682
1683static KEY_DIRECTIVE_IN_FIELDS_ARGS: LazyLock<ErrorCodeDefinition> =
1684    LazyLock::new(|| DIRECTIVE_IN_FIELDS_ARG.create_code("key".to_owned()));
1685static PROVIDES_DIRECTIVE_IN_FIELDS_ARGS: LazyLock<ErrorCodeDefinition> =
1686    LazyLock::new(|| DIRECTIVE_IN_FIELDS_ARG.create_code("provides".to_owned()));
1687static REQUIRES_DIRECTIVE_IN_FIELDS_ARGS: LazyLock<ErrorCodeDefinition> =
1688    LazyLock::new(|| DIRECTIVE_IN_FIELDS_ARG.create_code("requires".to_owned()));
1689
1690static EXTERNAL_UNUSED: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1691    ErrorCodeDefinition::new(
1692        "EXTERNAL_UNUSED".to_owned(),
1693        "An `@external` field is not being used by any instance of `@key`, `@requires`, `@provides` or to satisfy an interface implementation.".to_owned(),
1694        Some(ErrorCodeMetadata {
1695            added_in: FED1_CODE,
1696            replaces: &[],
1697        }),
1698)
1699});
1700
1701static TYPE_WITH_ONLY_UNUSED_EXTERNAL: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1702    ErrorCodeDefinition::new(
1703        "TYPE_WITH_ONLY_UNUSED_EXTERNAL".to_owned(),
1704        [
1705            "A federation 1 schema has a composite type comprised only of unused external fields.".to_owned(),
1706            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),
1707            "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()
1708        ].join(" "),
1709        None,
1710)
1711});
1712
1713static PROVIDES_ON_NON_OBJECT_FIELD: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1714    ErrorCodeDefinition::new(
1715        "PROVIDES_ON_NON_OBJECT_FIELD".to_owned(),
1716        "A `@provides` directive is used to mark a field whose base type is not an object type."
1717            .to_owned(),
1718        None,
1719    )
1720});
1721
1722static DIRECTIVE_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
1723    ErrorCodeCategory::new_federation_directive(
1724        "INVALID_FIELDS_TYPE".to_owned(),
1725        Box::new(|directive| {
1726            format!(
1727                "The value passed to the `fields` argument of a `@{directive}` directive is not a string."
1728            )
1729        }),
1730        None,
1731    )
1732});
1733
1734static KEY_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeDefinition> =
1735    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS_TYPE.create_code("key".to_owned()));
1736static PROVIDES_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeDefinition> =
1737    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS_TYPE.create_code("provides".to_owned()));
1738static REQUIRES_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeDefinition> =
1739    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS_TYPE.create_code("requires".to_owned()));
1740
1741static DIRECTIVE_INVALID_FIELDS: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
1742    ErrorCodeCategory::new_federation_directive(
1743        "INVALID_FIELDS".to_owned(),
1744        Box::new(|directive| {
1745            format!(
1746                "The `fields` argument of a `@{directive}` directive is invalid (it has invalid syntax, includes unknown fields, ...)."
1747            )
1748        }),
1749        None,
1750    )
1751});
1752
1753static KEY_INVALID_FIELDS: LazyLock<ErrorCodeDefinition> =
1754    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS.create_code("key".to_owned()));
1755static PROVIDES_INVALID_FIELDS: LazyLock<ErrorCodeDefinition> =
1756    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS.create_code("provides".to_owned()));
1757static REQUIRES_INVALID_FIELDS: LazyLock<ErrorCodeDefinition> =
1758    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS.create_code("requires".to_owned()));
1759
1760static KEY_FIELDS_SELECT_INVALID_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1761    ErrorCodeDefinition::new(
1762        "KEY_FIELDS_SELECT_INVALID_TYPE".to_owned(),
1763        "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(),
1764        Some(ErrorCodeMetadata {
1765            added_in: FED1_CODE,
1766            replaces: &[],
1767        }),
1768)
1769});
1770
1771static ROOT_TYPE_USED: LazyLock<ErrorCodeCategory<SchemaRootKind>> = LazyLock::new(|| {
1772    ErrorCodeCategory::new(
1773        Box::new(|element| {
1774            let kind: String = element.into();
1775            format!("ROOT_{}_USED", kind.to_uppercase())
1776        }),
1777        Box::new(|element| {
1778            let kind: String = element.into();
1779            format!(
1780                "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."
1781            )
1782        }),
1783        Some(ErrorCodeMetadata {
1784            added_in: FED1_CODE,
1785            replaces: &[],
1786        }),
1787    )
1788});
1789
1790static ROOT_QUERY_USED: LazyLock<ErrorCodeDefinition> =
1791    LazyLock::new(|| ROOT_TYPE_USED.create_code(SchemaRootKind::Query));
1792static ROOT_MUTATION_USED: LazyLock<ErrorCodeDefinition> =
1793    LazyLock::new(|| ROOT_TYPE_USED.create_code(SchemaRootKind::Mutation));
1794static ROOT_SUBSCRIPTION_USED: LazyLock<ErrorCodeDefinition> =
1795    LazyLock::new(|| ROOT_TYPE_USED.create_code(SchemaRootKind::Subscription));
1796
1797static INVALID_SUBGRAPH_NAME: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1798    ErrorCodeDefinition::new(
1799        "INVALID_SUBGRAPH_NAME".to_owned(),
1800        "A subgraph name is invalid (subgraph names cannot be a single underscore (\"_\"))."
1801            .to_owned(),
1802        None,
1803    )
1804});
1805
1806static NO_QUERIES: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1807    ErrorCodeDefinition::new(
1808        "NO_QUERIES".to_owned(),
1809        "None of the composed subgraphs expose any query.".to_owned(),
1810        None,
1811    )
1812});
1813
1814static INTERFACE_FIELD_NO_IMPLEM: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1815    ErrorCodeDefinition::new(
1816        "INTERFACE_FIELD_NO_IMPLEM".to_owned(),
1817        "After subgraph merging, an implementation is missing a field of one of the interface it implements (which can happen for valid subgraphs).".to_owned(),
1818        None,
1819    )
1820});
1821
1822static TYPE_KIND_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1823    ErrorCodeDefinition::new(
1824        "TYPE_KIND_MISMATCH".to_owned(),
1825        "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(),
1826        Some(ErrorCodeMetadata {
1827            replaces: &["VALUE_TYPE_KIND_MISMATCH", "EXTENSION_OF_WRONG_KIND", "ENUM_MISMATCH_TYPE"],
1828            ..DEFAULT_METADATA.clone()
1829        }),
1830    )
1831});
1832
1833static EXTERNAL_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1834    ErrorCodeDefinition::new(
1835        "EXTERNAL_TYPE_MISMATCH".to_owned(),
1836        "An `@external` field has a type that is incompatible with the declaration(s) of that field in other subgraphs.".to_owned(),
1837        Some(ErrorCodeMetadata {
1838            added_in: FED1_CODE,
1839            replaces: &[],
1840        }),
1841    )
1842});
1843
1844static EXTERNAL_COLLISION_WITH_ANOTHER_DIRECTIVE: LazyLock<ErrorCodeDefinition> =
1845    LazyLock::new(|| {
1846        ErrorCodeDefinition::new(
1847            "EXTERNAL_COLLISION_WITH_ANOTHER_DIRECTIVE".to_owned(),
1848            "The @external directive collides with other directives in some situations.".to_owned(),
1849            Some(ErrorCodeMetadata {
1850                added_in: "2.1.0",
1851                replaces: &[],
1852            }),
1853        )
1854    });
1855
1856static EXTERNAL_ARGUMENT_MISSING: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1857    ErrorCodeDefinition::new(
1858        "EXTERNAL_ARGUMENT_MISSING".to_owned(),
1859        "An `@external` field is missing some arguments present in the declaration(s) of that field in other subgraphs.".to_owned(),
1860        None,
1861    )
1862});
1863
1864static EXTERNAL_ARGUMENT_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1865    ErrorCodeDefinition::new(
1866        "EXTERNAL_ARGUMENT_TYPE_MISMATCH".to_owned(),
1867        "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(),
1868        None,
1869    )
1870});
1871
1872static EXTERNAL_ARGUMENT_DEFAULT_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1873    ErrorCodeDefinition::new(
1874        "EXTERNAL_ARGUMENT_DEFAULT_MISMATCH".to_owned(),
1875        "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(),
1876        None,
1877    )
1878});
1879
1880static EXTERNAL_ON_INTERFACE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1881    ErrorCodeDefinition::new(
1882        "EXTERNAL_ON_INTERFACE".to_owned(),
1883        "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(),
1884        None,
1885    )
1886});
1887
1888static MERGED_DIRECTIVE_APPLICATION_ON_EXTERNAL: LazyLock<ErrorCodeDefinition> = LazyLock::new(
1889    || {
1890        ErrorCodeDefinition::new(
1891        "MERGED_DIRECTIVE_APPLICATION_ON_EXTERNAL".to_owned(),
1892        "In a subgraph, a field is both marked @external and has a merged directive applied to it".to_owned(),
1893        None,
1894    )
1895    },
1896);
1897
1898static FIELD_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1899    ErrorCodeDefinition::new(
1900        "FIELD_TYPE_MISMATCH".to_owned(),
1901        "A field has a type that is incompatible with other declarations of that field in other subgraphs.".to_owned(),
1902        Some(ErrorCodeMetadata {
1903            replaces: &["VALUE_TYPE_FIELD_TYPE_MISMATCH"],
1904            ..DEFAULT_METADATA.clone()
1905        }),
1906    )
1907});
1908
1909static FIELD_ARGUMENT_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1910    ErrorCodeDefinition::new(
1911        "FIELD_ARGUMENT_TYPE_MISMATCH".to_owned(),
1912        "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(),
1913        Some(ErrorCodeMetadata {
1914            replaces: &["VALUE_TYPE_INPUT_VALUE_MISMATCH"],
1915            ..DEFAULT_METADATA.clone()
1916        }),
1917    )
1918});
1919
1920static INPUT_FIELD_DEFAULT_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1921    ErrorCodeDefinition::new(
1922        "INPUT_FIELD_DEFAULT_MISMATCH".to_owned(),
1923        "An input field has a default value that is incompatible with other declarations of that field in other subgraphs.".to_owned(),
1924        None,
1925    )
1926});
1927
1928static FIELD_ARGUMENT_DEFAULT_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1929    ErrorCodeDefinition::new(
1930        "FIELD_ARGUMENT_DEFAULT_MISMATCH".to_owned(),
1931        "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(),
1932        None,
1933    )
1934});
1935
1936static EXTENSION_WITH_NO_BASE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1937    ErrorCodeDefinition::new(
1938        "EXTENSION_WITH_NO_BASE".to_owned(),
1939        "A subgraph is attempting to `extend` a type that is not originally defined in any known subgraph.".to_owned(),
1940        Some(ErrorCodeMetadata {
1941            added_in: FED1_CODE,
1942            replaces: &[],
1943        }),
1944    )
1945});
1946
1947static EXTERNAL_MISSING_ON_BASE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1948    ErrorCodeDefinition::new(
1949        "EXTERNAL_MISSING_ON_BASE".to_owned(),
1950        "A field is marked as `@external` in a subgraph but with no non-external declaration in any other subgraph.".to_owned(),
1951        Some(ErrorCodeMetadata {
1952            added_in: FED1_CODE,
1953            replaces: &[],
1954        }),
1955    )
1956});
1957
1958static INVALID_FIELD_SHARING: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1959    ErrorCodeDefinition::new(
1960        "INVALID_FIELD_SHARING".to_owned(),
1961        "A field that is non-shareable in at least one subgraph is resolved by multiple subgraphs."
1962            .to_owned(),
1963        None,
1964    )
1965});
1966
1967static INVALID_SHAREABLE_USAGE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1968    ErrorCodeDefinition::new(
1969        "INVALID_SHAREABLE_USAGE".to_owned(),
1970        "The `@shareable` federation directive is used in an invalid way.".to_owned(),
1971        Some(ErrorCodeMetadata {
1972            added_in: "2.1.2",
1973            replaces: &[],
1974        }),
1975    )
1976});
1977
1978static INVALID_LINK_DIRECTIVE_USAGE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1979    ErrorCodeDefinition::new(
1980        "INVALID_LINK_DIRECTIVE_USAGE".to_owned(),
1981        "An application of the @link directive is invalid/does not respect the specification."
1982            .to_owned(),
1983        None,
1984    )
1985});
1986
1987static INVALID_LINK_IDENTIFIER: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1988    ErrorCodeDefinition::new(
1989        "INVALID_LINK_IDENTIFIER".to_owned(),
1990        "A url/version for a @link feature is invalid/does not respect the specification."
1991            .to_owned(),
1992        Some(ErrorCodeMetadata {
1993            added_in: "2.1.0",
1994            replaces: &[],
1995        }),
1996    )
1997});
1998
1999static LINK_IMPORT_NAME_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2000    ErrorCodeDefinition::new(
2001        "LINK_IMPORT_NAME_MISMATCH".to_owned(),
2002        "The import name for a merged directive (as declared by the relevant `@link(import:)` argument) is inconsistent between subgraphs.".to_owned(),
2003        None,
2004    )
2005});
2006
2007static REFERENCED_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2008    ErrorCodeDefinition::new(
2009        "REFERENCED_INACCESSIBLE".to_owned(),
2010        "An element is marked as @inaccessible but is referenced by an element visible in the API schema.".to_owned(),
2011        None,
2012    )
2013});
2014
2015static DEFAULT_VALUE_USES_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2016    ErrorCodeDefinition::new(
2017        "DEFAULT_VALUE_USES_INACCESSIBLE".to_owned(),
2018        "An element is marked as @inaccessible but is used in the default value of an element visible in the API schema.".to_owned(),
2019        None,
2020    )
2021});
2022
2023static QUERY_ROOT_TYPE_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2024    ErrorCodeDefinition::new(
2025        "QUERY_ROOT_TYPE_INACCESSIBLE".to_owned(),
2026        "An element is marked as @inaccessible but is the query root type, which must be visible in the API schema.".to_owned(),
2027        None,
2028    )
2029});
2030
2031static REQUIRED_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2032    ErrorCodeDefinition::new(
2033        "REQUIRED_INACCESSIBLE".to_owned(),
2034        "An element is marked as @inaccessible but is required by an element visible in the API schema.".to_owned(),
2035        None,
2036    )
2037});
2038
2039static IMPLEMENTED_BY_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2040    ErrorCodeDefinition::new(
2041        "IMPLEMENTED_BY_INACCESSIBLE".to_owned(),
2042        "An element is marked as @inaccessible but implements an element visible in the API schema.".to_owned(),
2043        None,
2044    )
2045});
2046
2047static DISALLOWED_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2048    ErrorCodeDefinition::new(
2049        "DISALLOWED_INACCESSIBLE".to_owned(),
2050        "An element is marked as @inaccessible that is not allowed to be @inaccessible.".to_owned(),
2051        None,
2052    )
2053});
2054
2055static ONLY_INACCESSIBLE_CHILDREN: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2056    ErrorCodeDefinition::new(
2057        "ONLY_INACCESSIBLE_CHILDREN".to_owned(),
2058        "A type visible in the API schema has only @inaccessible children.".to_owned(),
2059        None,
2060    )
2061});
2062
2063static REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2064    || {
2065        ErrorCodeDefinition::new(
2066        "REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH".to_owned(),
2067        "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(),
2068        None,
2069    )
2070    },
2071);
2072
2073static REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2074    || {
2075        ErrorCodeDefinition::new(
2076        "REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH".to_owned(),
2077        "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(),
2078        None,
2079    )
2080    },
2081);
2082
2083static EMPTY_MERGED_INPUT_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2084    ErrorCodeDefinition::new(
2085        "EMPTY_MERGED_INPUT_TYPE".to_owned(),
2086        "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(),
2087        None,
2088    )
2089});
2090
2091static INPUT_FIELD_MERGE_FAILED: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2092    ErrorCodeDefinition::new(
2093        "INPUT_FIELD_MERGE_FAILED".to_owned(),
2094        "Failed to merge an input object field due to incompatible definitions across subgraphs."
2095            .to_owned(),
2096        None,
2097    )
2098});
2099
2100static ENUM_VALUE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2101    ErrorCodeDefinition::new(
2102        "ENUM_VALUE_MISMATCH".to_owned(),
2103        "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(),
2104        None,
2105    )
2106});
2107
2108static EMPTY_MERGED_ENUM_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2109    ErrorCodeDefinition::new(
2110        "EMPTY_MERGED_ENUM_TYPE".to_owned(),
2111        "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(),
2112        None,
2113    )
2114});
2115
2116static SHAREABLE_HAS_MISMATCHED_RUNTIME_TYPES: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2117    || {
2118        ErrorCodeDefinition::new(
2119        "SHAREABLE_HAS_MISMATCHED_RUNTIME_TYPES".to_owned(),
2120        "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(),
2121        None,
2122    )
2123    },
2124);
2125
2126static SATISFIABILITY_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2127    ErrorCodeDefinition::new(
2128        "SATISFIABILITY_ERROR".to_owned(),
2129        "Subgraphs can be merged, but the resulting supergraph API would have queries that cannot be satisfied by those subgraphs.".to_owned(),
2130        None,
2131    )
2132});
2133
2134static MAX_VALIDATION_SUBGRAPH_PATHS_EXCEEDED: LazyLock<ErrorCodeDefinition> =
2135    LazyLock::new(|| {
2136        ErrorCodeDefinition::new(
2137            "MAX_VALIDATION_SUBGRAPH_PATHS_EXCEEDED".to_owned(),
2138            "The maximum number of validation subgraph paths has been exceeded.".to_owned(),
2139            Some(ErrorCodeMetadata {
2140                added_in: "2.8.0",
2141                replaces: &[],
2142            }),
2143        )
2144    });
2145
2146static OVERRIDE_FROM_SELF_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2147    ErrorCodeDefinition::new(
2148        "OVERRIDE_FROM_SELF_ERROR".to_owned(),
2149        "Field with `@override` directive has \"from\" location that references its own subgraph."
2150            .to_owned(),
2151        None,
2152    )
2153});
2154
2155static OVERRIDE_SOURCE_HAS_OVERRIDE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2156    ErrorCodeDefinition::new(
2157        "OVERRIDE_SOURCE_HAS_OVERRIDE".to_owned(),
2158        "Field which is overridden to another subgraph is also marked @override.".to_owned(),
2159        None,
2160    )
2161});
2162
2163static OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2164    || {
2165        ErrorCodeDefinition::new(
2166        "OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE".to_owned(),
2167        "The @override directive cannot be used on external fields, nor to override fields with either @external, @provides, or @requires.".to_owned(),
2168        None,
2169    )
2170    },
2171);
2172
2173static OVERRIDE_ON_INTERFACE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2174    ErrorCodeDefinition::new(
2175        "OVERRIDE_ON_INTERFACE".to_owned(),
2176        "The @override directive cannot be used on the fields of an interface type.".to_owned(),
2177        Some(ErrorCodeMetadata {
2178            added_in: "2.3.0",
2179            replaces: &[],
2180        }),
2181    )
2182});
2183
2184static OVERRIDE_LABEL_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2185    ErrorCodeDefinition::new(
2186        "OVERRIDE_LABEL_INVALID".to_owned(),
2187        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(),
2188        Some(ErrorCodeMetadata {
2189            added_in: "2.7.0",
2190            replaces: &[],
2191        }),
2192    )
2193});
2194
2195static UNSUPPORTED_FEATURE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2196    ErrorCodeDefinition::new(
2197        "UNSUPPORTED_FEATURE".to_owned(),
2198        "Indicates an error due to feature currently unsupported by federation.".to_owned(),
2199        Some(ErrorCodeMetadata {
2200            added_in: "2.1.0",
2201            replaces: &[],
2202        }),
2203    )
2204});
2205
2206static INVALID_FEDERATION_SUPERGRAPH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2207    ErrorCodeDefinition::new(
2208        "INVALID_FEDERATION_SUPERGRAPH".to_owned(),
2209        "Indicates that a schema provided for an Apollo Federation supergraph is not a valid supergraph schema.".to_owned(),
2210        Some(ErrorCodeMetadata {
2211            added_in: "2.1.0",
2212            replaces: &[],
2213        }),
2214    )
2215});
2216
2217static DOWNSTREAM_SERVICE_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2218    ErrorCodeDefinition::new(
2219        "DOWNSTREAM_SERVICE_ERROR".to_owned(),
2220        "Indicates an error in a subgraph service query during query execution in a federated service.".to_owned(),
2221        Some(ErrorCodeMetadata {
2222            added_in: FED1_CODE,
2223            replaces: &[],
2224        }),
2225    )
2226});
2227
2228static DIRECTIVE_COMPOSITION_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2229    ErrorCodeDefinition::new(
2230        "DIRECTIVE_COMPOSITION_ERROR".to_owned(),
2231        "Error when composing custom directives.".to_owned(),
2232        Some(ErrorCodeMetadata {
2233            added_in: "2.1.0",
2234            replaces: &[],
2235        }),
2236    )
2237});
2238
2239static INTERFACE_OBJECT_USAGE_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2240    ErrorCodeDefinition::new(
2241        "INTERFACE_OBJECT_USAGE_ERROR".to_owned(),
2242        "Error in the usage of the @interfaceObject directive.".to_owned(),
2243        Some(ErrorCodeMetadata {
2244            added_in: "2.3.0",
2245            replaces: &[],
2246        }),
2247    )
2248});
2249
2250static INTERFACE_KEY_NOT_ON_IMPLEMENTATION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2251    ErrorCodeDefinition::new(
2252        "INTERFACE_KEY_NOT_ON_IMPLEMENTATION".to_owned(),
2253        "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(),
2254        Some(ErrorCodeMetadata {
2255            added_in: "2.3.0",
2256            replaces: &[],
2257        }),
2258    )
2259});
2260
2261static INTERFACE_KEY_MISSING_IMPLEMENTATION_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2262    || {
2263        ErrorCodeDefinition::new(
2264        "INTERFACE_KEY_MISSING_IMPLEMENTATION_TYPE".to_owned(),
2265        "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(),
2266        Some(ErrorCodeMetadata {
2267            added_in: "2.3.0",
2268            replaces: &[],
2269        }),
2270    )
2271    },
2272);
2273
2274static INTERNAL: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2275    ErrorCodeDefinition::new(
2276        "INTERNAL".to_owned(),
2277        "An internal federation error occured.".to_owned(),
2278        None,
2279    )
2280});
2281
2282static ERROR_CODE_MISSING: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2283    ErrorCodeDefinition::new(
2284        "ERROR_CODE_MISSING".to_owned(),
2285        "An internal federation error occurred when translating a federation error into an error code".to_owned(),
2286        None,
2287    )
2288});
2289
2290static UNSUPPORTED_FEDERATION_VERSION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2291    ErrorCodeDefinition::new(
2292        "UNSUPPORTED_FEDERATION_VERSION".to_owned(),
2293        "Supergraphs composed with federation version 1 are not supported. Please recompose your supergraph with federation version 2 or greater".to_owned(),
2294        None,
2295    )
2296});
2297
2298static UNSUPPORTED_FEDERATION_DIRECTIVE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2299    ErrorCodeDefinition::new(
2300        "UNSUPPORTED_FEDERATION_DIRECTIVE".to_owned(),
2301        "Indicates that the specified specification version is outside of supported range"
2302            .to_owned(),
2303        None,
2304    )
2305});
2306
2307static QUERY_PLAN_COMPLEXITY_EXCEEDED: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2308    ErrorCodeDefinition::new(
2309        "QUERY_PLAN_COMPLEXITY_EXCEEDED".to_owned(),
2310        "Indicates that provided query has too many possible ways to generate a plan and cannot be planned in a reasonable amount of time"
2311            .to_owned(),
2312        None,
2313    )
2314});
2315
2316static NO_PLAN_FOUND_WITH_DISABLED_SUBGRAPHS: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2317    ErrorCodeDefinition::new(
2318        "NO_PLAN_FOUND_WITH_DISABLED_SUBGRAPHS".to_owned(),
2319        "Indicates that the provided query could not be query planned due to subgraphs being disabled"
2320            .to_owned(),
2321        None,
2322    )
2323});
2324
2325static COST_APPLIED_TO_INTERFACE_FIELD: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2326    ErrorCodeDefinition::new(
2327        "COST_APPLIED_TO_INTERFACE_FIELD".to_owned(),
2328        "The `@cost` directive must be applied to concrete types".to_owned(),
2329        Some(ErrorCodeMetadata {
2330            added_in: "2.9.2",
2331            replaces: &[],
2332        }),
2333    )
2334});
2335
2336static LIST_SIZE_APPLIED_TO_NON_LIST: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2337    ErrorCodeDefinition::new(
2338        "LIST_SIZE_APPLIED_TO_NON_LIST".to_owned(),
2339        "The `@listSize` directive must be applied to list types".to_owned(),
2340        Some(ErrorCodeMetadata {
2341            added_in: "2.9.2",
2342            replaces: &[],
2343        }),
2344    )
2345});
2346
2347static LIST_SIZE_INVALID_ASSUMED_SIZE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2348    ErrorCodeDefinition::new(
2349        "LIST_SIZE_INVALID_ASSUMED_SIZE".to_owned(),
2350        "The `@listSize` directive assumed size cannot be negative".to_owned(),
2351        Some(ErrorCodeMetadata {
2352            added_in: "2.9.2",
2353            replaces: &[],
2354        }),
2355    )
2356});
2357
2358static LIST_SIZE_INVALID_SLICING_ARGUMENT: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2359    ErrorCodeDefinition::new(
2360        "LIST_SIZE_INVALID_SLICING_ARGUMENT".to_owned(),
2361        "The `@listSize` directive must have existing integer slicing arguments".to_owned(),
2362        Some(ErrorCodeMetadata {
2363            added_in: "2.9.2",
2364            replaces: &[],
2365        }),
2366    )
2367});
2368
2369static LIST_SIZE_INVALID_SIZED_FIELD: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2370    ErrorCodeDefinition::new(
2371        "LIST_SIZE_INVALID_SIZED_FIELD".to_owned(),
2372        "The `@listSize` directive must reference existing list fields as sized fields".to_owned(),
2373        Some(ErrorCodeMetadata {
2374            added_in: "2.9.2",
2375            replaces: &[],
2376        }),
2377    )
2378});
2379
2380static CONTEXT_NAME_CONTAINS_UNDERSCORE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2381    ErrorCodeDefinition::new(
2382        "CONTEXT_NAME_CONTAINS_UNDERSCORE".to_owned(),
2383        "Context name is invalid.".to_owned(),
2384        Some(ErrorCodeMetadata {
2385            added_in: "2.8.0",
2386            replaces: &[],
2387        }),
2388    )
2389});
2390
2391static CONTEXT_NAME_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2392    ErrorCodeDefinition::new(
2393        "CONTEXT_NAME_INVALID".to_owned(),
2394        "Context name is invalid.".to_owned(),
2395        Some(ErrorCodeMetadata {
2396            added_in: "2.8.0",
2397            replaces: &[],
2398        }),
2399    )
2400});
2401
2402static CONTEXT_NOT_SET: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2403    ErrorCodeDefinition::new(
2404        "CONTEXT_NOT_SET".to_owned(),
2405        "Context is never set for context trying to be used".to_owned(),
2406        Some(ErrorCodeMetadata {
2407            added_in: "2.8.0",
2408            replaces: &[],
2409        }),
2410    )
2411});
2412
2413static NO_CONTEXT_REFERENCED: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2414    ErrorCodeDefinition::new(
2415        "NO_CONTEXT_REFERENCED".to_owned(),
2416        "Selection in @fromContext field argument does not reference a context".to_owned(),
2417        Some(ErrorCodeMetadata {
2418            added_in: "2.8.0",
2419            replaces: &[],
2420        }),
2421    )
2422});
2423
2424static NO_SELECTION_FOR_CONTEXT: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2425    ErrorCodeDefinition::new(
2426        "NO_SELECTION_FOR_CONTEXT".to_owned(),
2427        "field parameter in @fromContext must contain a selection set".to_owned(),
2428        Some(ErrorCodeMetadata {
2429            added_in: "2.8.0",
2430            replaces: &[],
2431        }),
2432    )
2433});
2434
2435static CONTEXT_NO_RESOLVABLE_KEY: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2436    ErrorCodeDefinition::new(
2437        "CONTEXT_NO_RESOLVABLE_KEY".to_owned(),
2438        "If an ObjectType uses a @fromContext, at least one of its keys must be resolvable"
2439            .to_owned(),
2440        Some(ErrorCodeMetadata {
2441            added_in: "2.8.0",
2442            replaces: &[],
2443        }),
2444    )
2445});
2446
2447static CONTEXT_SELECTION_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2448    ErrorCodeDefinition::new(
2449        "CONTEXT_SELECTION_INVALID".to_owned(),
2450        "The selection set is invalid".to_owned(),
2451        Some(ErrorCodeMetadata {
2452            added_in: "2.8.0",
2453            replaces: &[],
2454        }),
2455    )
2456});
2457
2458static INVALID_TAG_NAME: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2459    ErrorCodeDefinition::new(
2460        "INVALID_TAG_NAME".to_owned(),
2461        "Invalid value for argument \"name\" in application of @tag.".to_owned(),
2462        Some(ErrorCodeMetadata {
2463            added_in: "2.0.0",
2464            replaces: &[],
2465        }),
2466    )
2467});
2468
2469static CACHE_TAG_INVALID_FORMAT: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2470    ErrorCodeDefinition::new(
2471        "CACHE_TAG_INVALID_FORMAT".to_owned(),
2472        "Invalid format string in @cacheTag directive.".to_owned(),
2473        Some(ErrorCodeMetadata {
2474            added_in: "2.12.0",
2475            replaces: &[],
2476        }),
2477    )
2478});
2479
2480static CACHE_TAG_APPLIED_TO_NON_ROOT_FIELD: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2481    ErrorCodeDefinition::new(
2482        "CACHE_TAG_APPLIED_TO_NON_ROOT_FIELD".to_owned(),
2483        "@cacheTag on a field can only be applied on root fields.".to_owned(),
2484        Some(ErrorCodeMetadata {
2485            added_in: "2.12.0",
2486            replaces: &[],
2487        }),
2488    )
2489});
2490
2491static CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ROOT_FIELD: LazyLock<ErrorCodeDefinition> =
2492    LazyLock::new(|| {
2493        ErrorCodeDefinition::new(
2494            "CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ROOT_FIELD".to_owned(),
2495            "@cacheTag on root fields can only reference arguments using $args in format."
2496                .to_owned(),
2497            Some(ErrorCodeMetadata {
2498                added_in: "2.12.0",
2499                replaces: &[],
2500            }),
2501        )
2502    });
2503
2504static CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ENTITY: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2505    || {
2506        ErrorCodeDefinition::new(
2507            "CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ENTITY".to_owned(),
2508            "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(),
2509            Some(ErrorCodeMetadata {
2510                added_in: "2.12.0",
2511                replaces: &[],
2512            }),
2513        )
2514    },
2515);
2516
2517static CACHE_TAG_ENTITY_NOT_RESOLVABLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2518    ErrorCodeDefinition::new(
2519        "CACHE_TAG_ENTITY_NOT_RESOLVABLE".to_owned(),
2520        "@cacheTag can only apply on resolvable entities (object with at least one @key directive)."
2521            .to_owned(),
2522        Some(ErrorCodeMetadata {
2523            added_in: "2.12.0",
2524            replaces: &[],
2525        }),
2526    )
2527});
2528
2529static CONTEXTUAL_ARGUMENT_NOT_CONTEXTUAL_IN_ALL_SUBGRAPHS: LazyLock<ErrorCodeDefinition> =
2530    LazyLock::new(|| {
2531        ErrorCodeDefinition::new(
2532            "CONTEXTUAL_ARGUMENT_NOT_CONTEXTUAL_IN_ALL_SUBGRAPHS".to_owned(),
2533            "Argument on field is marked contextual in only some subgraphs".to_owned(),
2534            Some(ErrorCodeMetadata {
2535                added_in: "2.7.0",
2536                replaces: &[],
2537            }),
2538        )
2539    });
2540
2541static QUERY_ROOT_MISSING: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2542    ErrorCodeDefinition::new(
2543        "QUERY_ROOT_MISSING".to_owned(),
2544        "The schema has no query root type.".to_owned(),
2545        Some(ErrorCodeMetadata {
2546            added_in: "2.0.0",
2547            replaces: &[],
2548        }),
2549    )
2550});
2551
2552static AUTH_REQUIREMENTS_APPLIED_ON_INTERFACE: LazyLock<ErrorCodeDefinition> = LazyLock::new(
2553    || {
2554        ErrorCodeDefinition::new(
2555        "AUTH_REQUIREMENTS_APPLIED_ON_INTERFACE".to_owned(),
2556        "The @authenticated, @requiresScopes and @policy directive cannot be applied on interface, interface object or their fields.".to_owned(),
2557        Some(ErrorCodeMetadata {
2558            added_in: "2.9.4",
2559            replaces: &[],
2560        }),
2561    )
2562    },
2563);
2564
2565static MISSING_TRANSITIVE_AUTH_REQUIREMENTS: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
2566    ErrorCodeDefinition::new(
2567            "MISSING_TRANSITIVE_AUTH_REQUIREMENTS".to_owned(),
2568            "Field missing transitive @authenticated, @requiresScopes and/or @policy auth requirements needed to access dependent data.".to_owned(),
2569            Some(ErrorCodeMetadata {
2570                added_in: "2.9.4",
2571                replaces: &[],
2572            }),
2573        )
2574});
2575
2576#[derive(Debug, PartialEq, strum_macros::EnumIter)]
2577pub enum ErrorCode {
2578    ErrorCodeMissing,
2579    Internal,
2580    ExtensionWithNoBase,
2581    InvalidGraphQL,
2582    DirectiveDefinitionInvalid,
2583    TypeDefinitionInvalid,
2584    UnsupportedLinkedFeature,
2585    UnknownFederationLinkVersion,
2586    UnknownLinkVersion,
2587    KeyFieldsHasArgs,
2588    ProvidesFieldsHasArgs,
2589    ProvidesFieldsMissingExternal,
2590    RequiresFieldsMissingExternal,
2591    KeyUnsupportedOnInterface,
2592    ProvidesUnsupportedOnInterface,
2593    RequiresUnsupportedOnInterface,
2594    KeyDirectiveInFieldsArgs,
2595    ProvidesDirectiveInFieldsArgs,
2596    RequiresDirectiveInFieldsArgs,
2597    ExternalUnused,
2598    TypeWithOnlyUnusedExternal,
2599    ProvidesOnNonObjectField,
2600    KeyInvalidFieldsType,
2601    ProvidesInvalidFieldsType,
2602    RequiresInvalidFieldsType,
2603    KeyInvalidFields,
2604    ProvidesInvalidFields,
2605    RequiresInvalidFields,
2606    KeyFieldsSelectInvalidType,
2607    RootQueryUsed,
2608    RootMutationUsed,
2609    RootSubscriptionUsed,
2610    InvalidSubgraphName,
2611    NoQueries,
2612    InterfaceFieldNoImplem,
2613    TypeKindMismatch,
2614    ExternalTypeMismatch,
2615    ExternalCollisionWithAnotherDirective,
2616    ExternalArgumentMissing,
2617    ExternalArgumentTypeMismatch,
2618    ExternalArgumentDefaultMismatch,
2619    ExternalOnInterface,
2620    MergedDirectiveApplicationOnExternal,
2621    FieldTypeMismatch,
2622    FieldArgumentTypeMismatch,
2623    InputFieldDefaultMismatch,
2624    FieldArgumentDefaultMismatch,
2625    ExternalMissingOnBase,
2626    InvalidFieldSharing,
2627    InvalidShareableUsage,
2628    InvalidLinkDirectiveUsage,
2629    InvalidLinkIdentifier,
2630    LinkImportNameMismatch,
2631    ReferencedInaccessible,
2632    DefaultValueUsesInaccessible,
2633    QueryRootTypeInaccessible,
2634    RequiredInaccessible,
2635    ImplementedByInaccessible,
2636    DisallowedInaccessible,
2637    OnlyInaccessibleChildren,
2638    RequiredInputFieldMissingInSomeSubgraph,
2639    RequiredArgumentMissingInSomeSubgraph,
2640    EmptyMergedInputType,
2641    InputFieldMergeFailed,
2642    EnumValueMismatch,
2643    EmptyMergedEnumType,
2644    ShareableHasMismatchedRuntimeTypes,
2645    SatisfiabilityError,
2646    MaxValidationSubgraphPathsExceeded,
2647    OverrideFromSelfError,
2648    OverrideSourceHasOverride,
2649    OverrideCollisionWithAnotherDirective,
2650    OverrideOnInterface,
2651    UnsupportedFeature,
2652    InvalidFederationSupergraph,
2653    DownstreamServiceError,
2654    DirectiveCompositionError,
2655    InterfaceObjectUsageError,
2656    InterfaceKeyNotOnImplementation,
2657    InterfaceKeyMissingImplementationType,
2658    UnsupportedFederationVersion,
2659    UnsupportedFederationDirective,
2660    QueryPlanComplexityExceededError,
2661    NoPlanFoundWithDisabledSubgraphs,
2662    CostAppliedToInterfaceField,
2663    ListSizeAppliedToNonList,
2664    ListSizeInvalidAssumedSize,
2665    ListSizeInvalidSlicingArgument,
2666    ListSizeInvalidSizedField,
2667    ContextNameInvalid,
2668    ContextNameContainsUnderscore,
2669    ContextNotSet,
2670    NoContextReferenced,
2671    NoSelectionForContext,
2672    ContextNoResolvableKey,
2673    ContextSelectionInvalid,
2674    InvalidTagName,
2675    CacheTagInvalidFormat,
2676    CacheTagAppliedToNonRootField,
2677    CacheTagInvalidFormatArgumentOnRootField,
2678    CacheTagInvalidFormatArgumentOnEntity,
2679    CacheTagEntityNotResolvable,
2680    OverrideLabelInvalid,
2681    ContextualArgumentNotContextualInAllSubgraphs,
2682    QueryRootMissing,
2683    AuthRequirementsAppliedOnInterface,
2684    MissingTransitiveAuthRequirements,
2685}
2686
2687impl ErrorCode {
2688    pub fn definition(&self) -> &'static ErrorCodeDefinition {
2689        match self {
2690            ErrorCode::Internal => &INTERNAL,
2691            ErrorCode::ExtensionWithNoBase => &EXTENSION_WITH_NO_BASE,
2692            ErrorCode::InvalidGraphQL => &INVALID_GRAPHQL,
2693            ErrorCode::DirectiveDefinitionInvalid => &DIRECTIVE_DEFINITION_INVALID,
2694            ErrorCode::TypeDefinitionInvalid => &TYPE_DEFINITION_INVALID,
2695            ErrorCode::UnsupportedLinkedFeature => &UNSUPPORTED_LINKED_FEATURE,
2696            ErrorCode::UnknownFederationLinkVersion => &UNKNOWN_FEDERATION_LINK_VERSION,
2697            ErrorCode::UnknownLinkVersion => &UNKNOWN_LINK_VERSION,
2698            ErrorCode::KeyFieldsHasArgs => &KEY_FIELDS_HAS_ARGS,
2699            ErrorCode::ProvidesFieldsHasArgs => &PROVIDES_FIELDS_HAS_ARGS,
2700            ErrorCode::ProvidesFieldsMissingExternal => &PROVIDES_FIELDS_MISSING_EXTERNAL,
2701            ErrorCode::RequiresFieldsMissingExternal => &REQUIRES_FIELDS_MISSING_EXTERNAL,
2702            ErrorCode::KeyUnsupportedOnInterface => &KEY_UNSUPPORTED_ON_INTERFACE,
2703            ErrorCode::ProvidesUnsupportedOnInterface => &PROVIDES_UNSUPPORTED_ON_INTERFACE,
2704            ErrorCode::RequiresUnsupportedOnInterface => &REQUIRES_UNSUPPORTED_ON_INTERFACE,
2705            ErrorCode::KeyDirectiveInFieldsArgs => &KEY_DIRECTIVE_IN_FIELDS_ARGS,
2706            ErrorCode::ProvidesDirectiveInFieldsArgs => &PROVIDES_DIRECTIVE_IN_FIELDS_ARGS,
2707            ErrorCode::RequiresDirectiveInFieldsArgs => &REQUIRES_DIRECTIVE_IN_FIELDS_ARGS,
2708            ErrorCode::ExternalUnused => &EXTERNAL_UNUSED,
2709            ErrorCode::ExternalCollisionWithAnotherDirective => {
2710                &EXTERNAL_COLLISION_WITH_ANOTHER_DIRECTIVE
2711            }
2712            ErrorCode::TypeWithOnlyUnusedExternal => &TYPE_WITH_ONLY_UNUSED_EXTERNAL,
2713            ErrorCode::ProvidesOnNonObjectField => &PROVIDES_ON_NON_OBJECT_FIELD,
2714            ErrorCode::KeyInvalidFieldsType => &KEY_INVALID_FIELDS_TYPE,
2715            ErrorCode::ProvidesInvalidFieldsType => &PROVIDES_INVALID_FIELDS_TYPE,
2716            ErrorCode::RequiresInvalidFieldsType => &REQUIRES_INVALID_FIELDS_TYPE,
2717            ErrorCode::KeyInvalidFields => &KEY_INVALID_FIELDS,
2718            ErrorCode::ProvidesInvalidFields => &PROVIDES_INVALID_FIELDS,
2719            ErrorCode::RequiresInvalidFields => &REQUIRES_INVALID_FIELDS,
2720            ErrorCode::KeyFieldsSelectInvalidType => &KEY_FIELDS_SELECT_INVALID_TYPE,
2721            ErrorCode::RootQueryUsed => &ROOT_QUERY_USED,
2722            ErrorCode::RootMutationUsed => &ROOT_MUTATION_USED,
2723            ErrorCode::RootSubscriptionUsed => &ROOT_SUBSCRIPTION_USED,
2724            ErrorCode::InvalidSubgraphName => &INVALID_SUBGRAPH_NAME,
2725            ErrorCode::NoQueries => &NO_QUERIES,
2726            ErrorCode::InterfaceFieldNoImplem => &INTERFACE_FIELD_NO_IMPLEM,
2727            ErrorCode::TypeKindMismatch => &TYPE_KIND_MISMATCH,
2728            ErrorCode::ExternalTypeMismatch => &EXTERNAL_TYPE_MISMATCH,
2729            ErrorCode::ExternalArgumentMissing => &EXTERNAL_ARGUMENT_MISSING,
2730            ErrorCode::ExternalArgumentTypeMismatch => &EXTERNAL_ARGUMENT_TYPE_MISMATCH,
2731            ErrorCode::ExternalArgumentDefaultMismatch => &EXTERNAL_ARGUMENT_DEFAULT_MISMATCH,
2732            ErrorCode::ExternalOnInterface => &EXTERNAL_ON_INTERFACE,
2733            ErrorCode::MergedDirectiveApplicationOnExternal => {
2734                &MERGED_DIRECTIVE_APPLICATION_ON_EXTERNAL
2735            }
2736            ErrorCode::FieldTypeMismatch => &FIELD_TYPE_MISMATCH,
2737            ErrorCode::FieldArgumentTypeMismatch => &FIELD_ARGUMENT_TYPE_MISMATCH,
2738            ErrorCode::InputFieldDefaultMismatch => &INPUT_FIELD_DEFAULT_MISMATCH,
2739            ErrorCode::FieldArgumentDefaultMismatch => &FIELD_ARGUMENT_DEFAULT_MISMATCH,
2740            ErrorCode::ExternalMissingOnBase => &EXTERNAL_MISSING_ON_BASE,
2741            ErrorCode::InvalidFieldSharing => &INVALID_FIELD_SHARING,
2742            ErrorCode::InvalidShareableUsage => &INVALID_SHAREABLE_USAGE,
2743            ErrorCode::InvalidLinkDirectiveUsage => &INVALID_LINK_DIRECTIVE_USAGE,
2744            ErrorCode::InvalidLinkIdentifier => &INVALID_LINK_IDENTIFIER,
2745            ErrorCode::LinkImportNameMismatch => &LINK_IMPORT_NAME_MISMATCH,
2746            ErrorCode::ReferencedInaccessible => &REFERENCED_INACCESSIBLE,
2747            ErrorCode::DefaultValueUsesInaccessible => &DEFAULT_VALUE_USES_INACCESSIBLE,
2748            ErrorCode::QueryRootTypeInaccessible => &QUERY_ROOT_TYPE_INACCESSIBLE,
2749            ErrorCode::RequiredInaccessible => &REQUIRED_INACCESSIBLE,
2750            ErrorCode::ImplementedByInaccessible => &IMPLEMENTED_BY_INACCESSIBLE,
2751            ErrorCode::DisallowedInaccessible => &DISALLOWED_INACCESSIBLE,
2752            ErrorCode::OnlyInaccessibleChildren => &ONLY_INACCESSIBLE_CHILDREN,
2753            ErrorCode::RequiredInputFieldMissingInSomeSubgraph => {
2754                &REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH
2755            }
2756            ErrorCode::RequiredArgumentMissingInSomeSubgraph => {
2757                &REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH
2758            }
2759            ErrorCode::EmptyMergedInputType => &EMPTY_MERGED_INPUT_TYPE,
2760            ErrorCode::InputFieldMergeFailed => &INPUT_FIELD_MERGE_FAILED,
2761            ErrorCode::EnumValueMismatch => &ENUM_VALUE_MISMATCH,
2762            ErrorCode::EmptyMergedEnumType => &EMPTY_MERGED_ENUM_TYPE,
2763            ErrorCode::ShareableHasMismatchedRuntimeTypes => {
2764                &SHAREABLE_HAS_MISMATCHED_RUNTIME_TYPES
2765            }
2766            ErrorCode::SatisfiabilityError => &SATISFIABILITY_ERROR,
2767            ErrorCode::MaxValidationSubgraphPathsExceeded => {
2768                &MAX_VALIDATION_SUBGRAPH_PATHS_EXCEEDED
2769            }
2770            ErrorCode::OverrideFromSelfError => &OVERRIDE_FROM_SELF_ERROR,
2771            ErrorCode::OverrideSourceHasOverride => &OVERRIDE_SOURCE_HAS_OVERRIDE,
2772            ErrorCode::OverrideCollisionWithAnotherDirective => {
2773                &OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE
2774            }
2775            ErrorCode::OverrideOnInterface => &OVERRIDE_ON_INTERFACE,
2776            ErrorCode::UnsupportedFeature => &UNSUPPORTED_FEATURE,
2777            ErrorCode::InvalidFederationSupergraph => &INVALID_FEDERATION_SUPERGRAPH,
2778            ErrorCode::DownstreamServiceError => &DOWNSTREAM_SERVICE_ERROR,
2779            ErrorCode::DirectiveCompositionError => &DIRECTIVE_COMPOSITION_ERROR,
2780            ErrorCode::InterfaceObjectUsageError => &INTERFACE_OBJECT_USAGE_ERROR,
2781            ErrorCode::InterfaceKeyNotOnImplementation => &INTERFACE_KEY_NOT_ON_IMPLEMENTATION,
2782            ErrorCode::InterfaceKeyMissingImplementationType => {
2783                &INTERFACE_KEY_MISSING_IMPLEMENTATION_TYPE
2784            }
2785            ErrorCode::UnsupportedFederationVersion => &UNSUPPORTED_FEDERATION_VERSION,
2786            ErrorCode::UnsupportedFederationDirective => &UNSUPPORTED_FEDERATION_DIRECTIVE,
2787            ErrorCode::QueryPlanComplexityExceededError => &QUERY_PLAN_COMPLEXITY_EXCEEDED,
2788            ErrorCode::NoPlanFoundWithDisabledSubgraphs => &NO_PLAN_FOUND_WITH_DISABLED_SUBGRAPHS,
2789            ErrorCode::CostAppliedToInterfaceField => &COST_APPLIED_TO_INTERFACE_FIELD,
2790            ErrorCode::ListSizeAppliedToNonList => &LIST_SIZE_APPLIED_TO_NON_LIST,
2791            ErrorCode::ListSizeInvalidAssumedSize => &LIST_SIZE_INVALID_ASSUMED_SIZE,
2792            ErrorCode::ListSizeInvalidSlicingArgument => &LIST_SIZE_INVALID_SLICING_ARGUMENT,
2793            ErrorCode::ListSizeInvalidSizedField => &LIST_SIZE_INVALID_SIZED_FIELD,
2794            ErrorCode::ContextNameContainsUnderscore => &CONTEXT_NAME_CONTAINS_UNDERSCORE,
2795            ErrorCode::ContextNameInvalid => &CONTEXT_NAME_INVALID,
2796            ErrorCode::ContextNotSet => &CONTEXT_NOT_SET,
2797            ErrorCode::NoContextReferenced => &NO_CONTEXT_REFERENCED,
2798            ErrorCode::NoSelectionForContext => &NO_SELECTION_FOR_CONTEXT,
2799            ErrorCode::ContextNoResolvableKey => &CONTEXT_NO_RESOLVABLE_KEY,
2800            ErrorCode::ContextSelectionInvalid => &CONTEXT_SELECTION_INVALID,
2801            ErrorCode::InvalidTagName => &INVALID_TAG_NAME,
2802            ErrorCode::CacheTagInvalidFormat => &CACHE_TAG_INVALID_FORMAT,
2803            ErrorCode::CacheTagAppliedToNonRootField => &CACHE_TAG_APPLIED_TO_NON_ROOT_FIELD,
2804            ErrorCode::CacheTagInvalidFormatArgumentOnRootField => {
2805                &CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ROOT_FIELD
2806            }
2807            ErrorCode::CacheTagInvalidFormatArgumentOnEntity => {
2808                &CACHE_TAG_INVALID_FORMAT_ARGUMENT_ON_ENTITY
2809            }
2810            ErrorCode::CacheTagEntityNotResolvable => &CACHE_TAG_ENTITY_NOT_RESOLVABLE,
2811            ErrorCode::ErrorCodeMissing => &ERROR_CODE_MISSING,
2812            ErrorCode::OverrideLabelInvalid => &OVERRIDE_LABEL_INVALID,
2813            ErrorCode::ContextualArgumentNotContextualInAllSubgraphs => {
2814                &CONTEXTUAL_ARGUMENT_NOT_CONTEXTUAL_IN_ALL_SUBGRAPHS
2815            }
2816            ErrorCode::QueryRootMissing => &QUERY_ROOT_MISSING,
2817            ErrorCode::AuthRequirementsAppliedOnInterface => {
2818                &AUTH_REQUIREMENTS_APPLIED_ON_INTERFACE
2819            }
2820            ErrorCode::MissingTransitiveAuthRequirements => &MISSING_TRANSITIVE_AUTH_REQUIREMENTS,
2821        }
2822    }
2823}