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