Skip to main content

apollo_federation/error/
mod.rs

1use std::cmp::Ordering;
2use std::fmt::Display;
3use std::fmt::Formatter;
4use std::fmt::Write;
5use std::sync::LazyLock;
6
7use apollo_compiler::InvalidNameError;
8use apollo_compiler::Name;
9use apollo_compiler::validation::DiagnosticList;
10use apollo_compiler::validation::WithErrors;
11
12use crate::subgraph::spec::FederationSpecError;
13
14/// Create an internal error.
15///
16/// # Example
17/// ```rust
18/// use apollo_federation::internal_error;
19/// use apollo_federation::error::FederationError;
20/// # fn may_be_none() -> Option<()> { None }
21///
22/// const NAME: &str = "the thing";
23/// let result: Result<(), FederationError> = may_be_none()
24///     .ok_or_else(|| internal_error!("Expected {NAME} to be Some"));
25/// ```
26#[macro_export]
27macro_rules! internal_error {
28    ( $( $arg:tt )+ ) => {
29        $crate::error::FederationError::internal(format!( $( $arg )+ ))
30    }
31}
32
33/// Break out of the current function, returning an internal error.
34///
35/// # Example
36/// ```rust
37/// use apollo_federation::bail;
38/// use apollo_federation::error::FederationError;
39/// # fn may_be_none() -> Option<()> { None }
40///
41/// fn example() -> Result<(), FederationError> {
42///     bail!("Something went horribly wrong");
43///     unreachable!()
44/// }
45/// #
46/// # _ = example();
47/// ```
48#[macro_export]
49macro_rules! bail {
50    ( $( $arg:tt )+ ) => {
51        return Err($crate::internal_error!( $( $arg )+ ).into())
52    }
53}
54
55/// A safe assertion: in debug mode, it panicks on failure, and in production, it returns an
56/// internal error.
57///
58/// Treat this as an assertion. It must only be used for conditions that *should never happen*
59/// in normal operation.
60///
61/// # Example
62/// ```rust,no_run
63/// use apollo_federation::ensure;
64/// use apollo_federation::error::FederationError;
65/// # fn may_be_none() -> Option<()> { None }
66///
67/// fn example() -> Result<(), FederationError> {
68///     ensure!(1 == 0, "Something went horribly wrong");
69///     unreachable!()
70/// }
71/// ```
72#[macro_export]
73macro_rules! ensure {
74    ( $expr:expr, $( $arg:tt )+ ) => {
75        #[cfg(debug_assertions)]
76        {
77            if false {
78                return Err($crate::error::FederationError::internal("ensure!() must be used in a function that returns a Result").into());
79            }
80            assert!($expr, $( $arg )+);
81        }
82
83        #[cfg(not(debug_assertions))]
84        if !$expr {
85            $crate::bail!( $( $arg )+ );
86        }
87    }
88}
89
90// What we really needed here was the string representations in enum form, this isn't meant to
91// replace AST components.
92#[derive(Clone, Debug, strum_macros::Display)]
93enum SchemaRootKind {
94    #[strum(to_string = "query")]
95    Query,
96    #[strum(to_string = "mutation")]
97    Mutation,
98    #[strum(to_string = "subscription")]
99    Subscription,
100}
101
102impl From<SchemaRootKind> for String {
103    fn from(value: SchemaRootKind) -> Self {
104        value.to_string()
105    }
106}
107
108#[derive(Clone, Debug, strum_macros::Display, PartialEq, Eq)]
109pub enum UnsupportedFeatureKind {
110    #[strum(to_string = "alias")]
111    Alias,
112}
113
114#[derive(Debug, Clone, thiserror::Error)]
115pub enum SingleFederationError {
116    #[error(
117        "An internal error has occurred, please report this bug to Apollo.\n\nDetails: {message}"
118    )]
119    Internal { message: String },
120    #[error("An internal error has occurred, please report this bug to Apollo. Details: {0}")]
121    #[allow(private_interfaces)] // users should not inspect this.
122    InternalRebaseError(#[from] crate::operation::RebaseError),
123    // This is a known bug that will take time to fix, and does not require reporting.
124    #[error("{message}")]
125    InternalUnmergeableFields { message: String },
126    #[error("{diagnostics}")]
127    InvalidGraphQL { diagnostics: DiagnosticList },
128    #[error(transparent)]
129    InvalidGraphQLName(#[from] InvalidNameError),
130    #[error("Subgraph invalid: {message}")]
131    InvalidSubgraph { message: String },
132    #[error("Operation name not found")]
133    UnknownOperation,
134    #[error("Must provide operation name if query contains multiple operations")]
135    OperationNameNotProvided,
136    #[error(r#"{message} in @fromContext substring "{context}""#)]
137    FromContextParseError { context: String, message: String },
138    #[error(
139        "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."
140    )]
141    UnsupportedSpreadDirective { name: Name },
142    #[error("{message}")]
143    DirectiveDefinitionInvalid { message: String },
144    #[error("{message}")]
145    TypeDefinitionInvalid { message: String },
146    #[error("{message}")]
147    UnsupportedFederationDirective { message: String },
148    #[error("{message}")]
149    UnsupportedFederationVersion { message: String },
150    #[error("{message}")]
151    UnsupportedLinkedFeature { message: String },
152    #[error("{message}")]
153    UnknownFederationLinkVersion { message: String },
154    #[error("{message}")]
155    UnknownLinkVersion { message: String },
156    #[error("{message}")]
157    KeyFieldsHasArgs { message: String },
158    #[error("{message}")]
159    ProvidesFieldsHasArgs { message: String },
160    #[error("{message}")]
161    ProvidesFieldsMissingExternal { message: String },
162    #[error("{message}")]
163    RequiresFieldsMissingExternal { message: String },
164    #[error("{message}")]
165    KeyUnsupportedOnInterface { message: String },
166    #[error("{message}")]
167    ProvidesUnsupportedOnInterface { message: String },
168    #[error("{message}")]
169    RequiresUnsupportedOnInterface { message: String },
170    #[error("{message}")]
171    KeyDirectiveInFieldsArgs { message: String },
172    #[error("{message}")]
173    ProvidesDirectiveInFieldsArgs { message: String },
174    #[error("{message}")]
175    RequiresDirectiveInFieldsArgs { message: String },
176    #[error("{message}")]
177    ExternalUnused { message: String },
178    #[error("{message}")]
179    TypeWithOnlyUnusedExternal { message: String },
180    #[error("{message}")]
181    ProvidesOnNonObjectField { message: String },
182    #[error("{message}")]
183    KeyInvalidFieldsType { message: String },
184    #[error("{message}")]
185    ProvidesInvalidFieldsType { message: String },
186    #[error("{message}")]
187    RequiresInvalidFieldsType { message: String },
188    #[error("{message}")]
189    KeyInvalidFields { message: String },
190    #[error("{message}")]
191    ProvidesInvalidFields { message: String },
192    #[error("{message}")]
193    RequiresInvalidFields { message: String },
194    #[error("{message}")]
195    KeyFieldsSelectInvalidType { message: String },
196    #[error("{message}")]
197    RootQueryUsed { message: String },
198    #[error("{message}")]
199    RootMutationUsed { message: String },
200    #[error("{message}")]
201    RootSubscriptionUsed { message: String },
202    #[error("{message}")]
203    InvalidSubgraphName { message: String },
204    #[error("{message}")]
205    NoQueries { message: String },
206    #[error("{message}")]
207    InterfaceFieldNoImplem { message: String },
208    #[error("{message}")]
209    TypeKindMismatch { message: String },
210    #[error("{message}")]
211    ExternalTypeMismatch { message: String },
212    #[error("{message}")]
213    ExternalCollisionWithAnotherDirective { message: String },
214    #[error("{message}")]
215    ExternalArgumentMissing { message: String },
216    #[error("{message}")]
217    ExternalArgumentTypeMismatch { message: String },
218    #[error("{message}")]
219    ExternalArgumentDefaultMismatch { message: String },
220    #[error("{message}")]
221    ExternalOnInterface { message: String },
222    #[error("{message}")]
223    MergedDirectiveApplicationOnExternal { message: String },
224    #[error("{message}")]
225    FieldTypeMismatch { message: String },
226    #[error("{message}")]
227    FieldArgumentTypeMismatch { message: String },
228    #[error("{message}")]
229    InputFieldDefaultMismatch { message: String },
230    #[error("{message}")]
231    FieldArgumentDefaultMismatch { message: String },
232    #[error("{message}")]
233    ExtensionWithNoBase { message: String },
234    #[error("{message}")]
235    ExternalMissingOnBase { message: String },
236    #[error("{message}")]
237    InvalidFieldSharing { message: String },
238    #[error("{message}")]
239    InvalidShareableUsage { message: String },
240    #[error("{message}")]
241    InvalidLinkDirectiveUsage { message: String },
242    #[error("{message}")]
243    InvalidLinkIdentifier { message: String },
244    #[error("{message}")]
245    LinkImportNameMismatch { message: String },
246    #[error("{message}")]
247    ReferencedInaccessible { message: String },
248    #[error("{message}")]
249    DefaultValueUsesInaccessible { message: String },
250    #[error("{message}")]
251    QueryRootTypeInaccessible { message: String },
252    #[error("{message}")]
253    RequiredInaccessible { message: String },
254    #[error("{message}")]
255    ImplementedByInaccessible { message: String },
256    #[error("{message}")]
257    DisallowedInaccessible { message: String },
258    #[error("{message}")]
259    OnlyInaccessibleChildren { message: String },
260    #[error("{message}")]
261    RequiredInputFieldMissingInSomeSubgraph { message: String },
262    #[error("{message}")]
263    RequiredArgumentMissingInSomeSubgraph { message: String },
264    #[error("{message}")]
265    EmptyMergedInputType { message: String },
266    #[error("{message}")]
267    EnumValueMismatch { message: String },
268    #[error("{message}")]
269    EmptyMergedEnumType { message: String },
270    #[error("{message}")]
271    ShareableHasMismatchedRuntimeTypes { message: String },
272    #[error("{message}")]
273    SatisfiabilityError { message: String },
274    #[error("{message}")]
275    OverrideFromSelfError { message: String },
276    #[error("{message}")]
277    OverrideSourceHasOverride { message: String },
278    #[error("{message}")]
279    OverrideCollisionWithAnotherDirective { message: String },
280    #[error("{message}")]
281    OverrideOnInterface { message: String },
282    #[error("{message}")]
283    UnsupportedFeature {
284        message: String,
285        kind: UnsupportedFeatureKind,
286    },
287    #[error("{message}")]
288    InvalidFederationSupergraph { message: String },
289    #[error("{message}")]
290    DownstreamServiceError { message: String },
291    #[error("{message}")]
292    DirectiveCompositionError { message: String },
293    #[error("{message}")]
294    InterfaceObjectUsageError { message: String },
295    #[error("{message}")]
296    InterfaceKeyNotOnImplementation { message: String },
297    #[error("{message}")]
298    InterfaceKeyMissingImplementationType { message: String },
299    #[error("@defer is not supported on subscriptions")]
300    DeferredSubscriptionUnsupported,
301    #[error("{message}")]
302    QueryPlanComplexityExceeded { message: String },
303}
304
305impl SingleFederationError {
306    pub fn code(&self) -> ErrorCode {
307        match self {
308            SingleFederationError::Internal { .. } => ErrorCode::Internal,
309            SingleFederationError::InternalRebaseError { .. } => ErrorCode::Internal,
310            SingleFederationError::InternalUnmergeableFields { .. } => ErrorCode::Internal,
311            SingleFederationError::InvalidGraphQL { .. }
312            | SingleFederationError::InvalidGraphQLName(_) => ErrorCode::InvalidGraphQL,
313            SingleFederationError::InvalidSubgraph { .. } => ErrorCode::InvalidGraphQL,
314            // Technically it's not invalid graphql, but it is invalid syntax inside graphql...
315            SingleFederationError::FromContextParseError { .. } => ErrorCode::InvalidGraphQL,
316            // TODO(@goto-bus-stop): this should have a different error code: it's not invalid,
317            // just unsupported due to internal limitations.
318            SingleFederationError::UnsupportedSpreadDirective { .. } => ErrorCode::InvalidGraphQL,
319            // TODO(@goto-bus-stop): this should have a different error code: it's not the graphql
320            // that's invalid, but the operation name
321            SingleFederationError::UnknownOperation => ErrorCode::InvalidGraphQL,
322            SingleFederationError::OperationNameNotProvided => ErrorCode::InvalidGraphQL,
323            SingleFederationError::DirectiveDefinitionInvalid { .. } => {
324                ErrorCode::DirectiveDefinitionInvalid
325            }
326            SingleFederationError::TypeDefinitionInvalid { .. } => ErrorCode::TypeDefinitionInvalid,
327            SingleFederationError::UnsupportedFederationDirective { .. } => {
328                ErrorCode::UnsupportedFederationDirective
329            }
330            SingleFederationError::UnsupportedFederationVersion { .. } => {
331                ErrorCode::UnsupportedFederationVersion
332            }
333
334            SingleFederationError::UnsupportedLinkedFeature { .. } => {
335                ErrorCode::UnsupportedLinkedFeature
336            }
337            SingleFederationError::UnknownFederationLinkVersion { .. } => {
338                ErrorCode::UnknownFederationLinkVersion
339            }
340            SingleFederationError::UnknownLinkVersion { .. } => ErrorCode::UnknownLinkVersion,
341            SingleFederationError::KeyFieldsHasArgs { .. } => ErrorCode::KeyFieldsHasArgs,
342            SingleFederationError::ProvidesFieldsHasArgs { .. } => ErrorCode::ProvidesFieldsHasArgs,
343            SingleFederationError::ProvidesFieldsMissingExternal { .. } => {
344                ErrorCode::ProvidesFieldsMissingExternal
345            }
346            SingleFederationError::RequiresFieldsMissingExternal { .. } => {
347                ErrorCode::RequiresFieldsMissingExternal
348            }
349            SingleFederationError::KeyUnsupportedOnInterface { .. } => {
350                ErrorCode::KeyUnsupportedOnInterface
351            }
352            SingleFederationError::ProvidesUnsupportedOnInterface { .. } => {
353                ErrorCode::ProvidesUnsupportedOnInterface
354            }
355            SingleFederationError::RequiresUnsupportedOnInterface { .. } => {
356                ErrorCode::RequiresUnsupportedOnInterface
357            }
358            SingleFederationError::KeyDirectiveInFieldsArgs { .. } => {
359                ErrorCode::KeyDirectiveInFieldsArgs
360            }
361            SingleFederationError::ProvidesDirectiveInFieldsArgs { .. } => {
362                ErrorCode::ProvidesDirectiveInFieldsArgs
363            }
364            SingleFederationError::RequiresDirectiveInFieldsArgs { .. } => {
365                ErrorCode::RequiresDirectiveInFieldsArgs
366            }
367            SingleFederationError::ExternalUnused { .. } => ErrorCode::ExternalUnused,
368            SingleFederationError::TypeWithOnlyUnusedExternal { .. } => {
369                ErrorCode::TypeWithOnlyUnusedExternal
370            }
371            SingleFederationError::ProvidesOnNonObjectField { .. } => {
372                ErrorCode::ProvidesOnNonObjectField
373            }
374            SingleFederationError::KeyInvalidFieldsType { .. } => ErrorCode::KeyInvalidFieldsType,
375            SingleFederationError::ProvidesInvalidFieldsType { .. } => {
376                ErrorCode::ProvidesInvalidFieldsType
377            }
378            SingleFederationError::RequiresInvalidFieldsType { .. } => {
379                ErrorCode::RequiresInvalidFieldsType
380            }
381            SingleFederationError::KeyInvalidFields { .. } => ErrorCode::KeyInvalidFields,
382            SingleFederationError::ProvidesInvalidFields { .. } => ErrorCode::ProvidesInvalidFields,
383            SingleFederationError::RequiresInvalidFields { .. } => ErrorCode::RequiresInvalidFields,
384            SingleFederationError::KeyFieldsSelectInvalidType { .. } => {
385                ErrorCode::KeyFieldsSelectInvalidType
386            }
387            SingleFederationError::RootQueryUsed { .. } => ErrorCode::RootQueryUsed,
388            SingleFederationError::RootMutationUsed { .. } => ErrorCode::RootMutationUsed,
389            SingleFederationError::RootSubscriptionUsed { .. } => ErrorCode::RootSubscriptionUsed,
390            SingleFederationError::InvalidSubgraphName { .. } => ErrorCode::InvalidSubgraphName,
391            SingleFederationError::NoQueries { .. } => ErrorCode::NoQueries,
392            SingleFederationError::InterfaceFieldNoImplem { .. } => {
393                ErrorCode::InterfaceFieldNoImplem
394            }
395            SingleFederationError::TypeKindMismatch { .. } => ErrorCode::TypeKindMismatch,
396            SingleFederationError::ExternalTypeMismatch { .. } => ErrorCode::ExternalTypeMismatch,
397            SingleFederationError::ExternalCollisionWithAnotherDirective { .. } => {
398                ErrorCode::ExternalCollisionWithAnotherDirective
399            }
400            SingleFederationError::ExternalArgumentMissing { .. } => {
401                ErrorCode::ExternalArgumentMissing
402            }
403            SingleFederationError::ExternalArgumentTypeMismatch { .. } => {
404                ErrorCode::ExternalArgumentTypeMismatch
405            }
406            SingleFederationError::ExternalArgumentDefaultMismatch { .. } => {
407                ErrorCode::ExternalArgumentDefaultMismatch
408            }
409            SingleFederationError::ExternalOnInterface { .. } => ErrorCode::ExternalOnInterface,
410            SingleFederationError::MergedDirectiveApplicationOnExternal { .. } => {
411                ErrorCode::MergedDirectiveApplicationOnExternal
412            }
413            SingleFederationError::FieldTypeMismatch { .. } => ErrorCode::FieldTypeMismatch,
414            SingleFederationError::FieldArgumentTypeMismatch { .. } => {
415                ErrorCode::FieldArgumentTypeMismatch
416            }
417            SingleFederationError::InputFieldDefaultMismatch { .. } => {
418                ErrorCode::InputFieldDefaultMismatch
419            }
420            SingleFederationError::FieldArgumentDefaultMismatch { .. } => {
421                ErrorCode::FieldArgumentDefaultMismatch
422            }
423            SingleFederationError::ExtensionWithNoBase { .. } => ErrorCode::ExtensionWithNoBase,
424            SingleFederationError::ExternalMissingOnBase { .. } => ErrorCode::ExternalMissingOnBase,
425            SingleFederationError::InvalidFieldSharing { .. } => ErrorCode::InvalidFieldSharing,
426            SingleFederationError::InvalidShareableUsage { .. } => ErrorCode::InvalidShareableUsage,
427            SingleFederationError::InvalidLinkDirectiveUsage { .. } => {
428                ErrorCode::InvalidLinkDirectiveUsage
429            }
430            SingleFederationError::InvalidLinkIdentifier { .. } => ErrorCode::InvalidLinkIdentifier,
431            SingleFederationError::LinkImportNameMismatch { .. } => {
432                ErrorCode::LinkImportNameMismatch
433            }
434            SingleFederationError::ReferencedInaccessible { .. } => {
435                ErrorCode::ReferencedInaccessible
436            }
437            SingleFederationError::DefaultValueUsesInaccessible { .. } => {
438                ErrorCode::DefaultValueUsesInaccessible
439            }
440            SingleFederationError::QueryRootTypeInaccessible { .. } => {
441                ErrorCode::QueryRootTypeInaccessible
442            }
443            SingleFederationError::RequiredInaccessible { .. } => ErrorCode::RequiredInaccessible,
444            SingleFederationError::ImplementedByInaccessible { .. } => {
445                ErrorCode::ImplementedByInaccessible
446            }
447            SingleFederationError::DisallowedInaccessible { .. } => {
448                ErrorCode::DisallowedInaccessible
449            }
450            SingleFederationError::OnlyInaccessibleChildren { .. } => {
451                ErrorCode::OnlyInaccessibleChildren
452            }
453            SingleFederationError::RequiredInputFieldMissingInSomeSubgraph { .. } => {
454                ErrorCode::RequiredInputFieldMissingInSomeSubgraph
455            }
456            SingleFederationError::RequiredArgumentMissingInSomeSubgraph { .. } => {
457                ErrorCode::RequiredArgumentMissingInSomeSubgraph
458            }
459            SingleFederationError::EmptyMergedInputType { .. } => ErrorCode::EmptyMergedInputType,
460            SingleFederationError::EnumValueMismatch { .. } => ErrorCode::EnumValueMismatch,
461            SingleFederationError::EmptyMergedEnumType { .. } => ErrorCode::EmptyMergedEnumType,
462            SingleFederationError::ShareableHasMismatchedRuntimeTypes { .. } => {
463                ErrorCode::ShareableHasMismatchedRuntimeTypes
464            }
465            SingleFederationError::SatisfiabilityError { .. } => ErrorCode::SatisfiabilityError,
466            SingleFederationError::OverrideFromSelfError { .. } => ErrorCode::OverrideFromSelfError,
467            SingleFederationError::OverrideSourceHasOverride { .. } => {
468                ErrorCode::OverrideSourceHasOverride
469            }
470            SingleFederationError::OverrideCollisionWithAnotherDirective { .. } => {
471                ErrorCode::OverrideCollisionWithAnotherDirective
472            }
473            SingleFederationError::OverrideOnInterface { .. } => ErrorCode::OverrideOnInterface,
474            SingleFederationError::UnsupportedFeature { .. } => ErrorCode::UnsupportedFeature,
475            SingleFederationError::InvalidFederationSupergraph { .. } => {
476                ErrorCode::InvalidFederationSupergraph
477            }
478            SingleFederationError::DownstreamServiceError { .. } => {
479                ErrorCode::DownstreamServiceError
480            }
481            SingleFederationError::DirectiveCompositionError { .. } => {
482                ErrorCode::DirectiveCompositionError
483            }
484            SingleFederationError::InterfaceObjectUsageError { .. } => {
485                ErrorCode::InterfaceObjectUsageError
486            }
487            SingleFederationError::InterfaceKeyNotOnImplementation { .. } => {
488                ErrorCode::InterfaceKeyNotOnImplementation
489            }
490            SingleFederationError::InterfaceKeyMissingImplementationType { .. } => {
491                ErrorCode::InterfaceKeyMissingImplementationType
492            }
493            SingleFederationError::DeferredSubscriptionUnsupported => ErrorCode::Internal,
494            SingleFederationError::QueryPlanComplexityExceeded { .. } => {
495                ErrorCode::QueryPlanComplexityExceededError
496            }
497        }
498    }
499}
500
501impl From<InvalidNameError> for FederationError {
502    fn from(err: InvalidNameError) -> Self {
503        SingleFederationError::from(err).into()
504    }
505}
506
507impl From<FederationSpecError> for FederationError {
508    fn from(err: FederationSpecError) -> Self {
509        // TODO: When we get around to finishing the composition port, we should really switch it to
510        // using FederationError instead of FederationSpecError.
511        let message = err.to_string();
512        match err {
513            FederationSpecError::UnsupportedVersionError { .. } => {
514                SingleFederationError::UnsupportedFederationVersion { message }.into()
515            }
516            FederationSpecError::UnsupportedFederationDirective { .. } => {
517                SingleFederationError::UnsupportedFederationDirective { message }.into()
518            }
519            FederationSpecError::InvalidGraphQLName(message) => message.into(),
520        }
521    }
522}
523
524#[derive(Debug, Clone, thiserror::Error)]
525pub struct MultipleFederationErrors {
526    pub errors: Vec<SingleFederationError>,
527}
528
529impl MultipleFederationErrors {
530    pub fn push(&mut self, error: FederationError) {
531        match error {
532            FederationError::SingleFederationError(error) => {
533                self.errors.push(error);
534            }
535            FederationError::MultipleFederationErrors(errors) => {
536                self.errors.extend(errors.errors);
537            }
538            FederationError::AggregateFederationError(errors) => {
539                self.errors.extend(errors.causes);
540            }
541        }
542    }
543}
544
545impl Display for MultipleFederationErrors {
546    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
547        write!(f, "The following errors occurred:")?;
548        for error in &self.errors {
549            write!(f, "\n  - ")?;
550            for c in error.to_string().chars() {
551                if c == '\n' {
552                    write!(f, "\n    ")?;
553                } else {
554                    f.write_char(c)?;
555                }
556            }
557        }
558        Ok(())
559    }
560}
561
562impl From<DiagnosticList> for SingleFederationError {
563    fn from(diagnostics: DiagnosticList) -> Self {
564        SingleFederationError::InvalidGraphQL { diagnostics }
565    }
566}
567
568impl FromIterator<SingleFederationError> for MultipleFederationErrors {
569    fn from_iter<T: IntoIterator<Item = SingleFederationError>>(iter: T) -> Self {
570        Self {
571            errors: iter.into_iter().collect(),
572        }
573    }
574}
575
576#[derive(Debug, Clone, thiserror::Error)]
577pub struct AggregateFederationError {
578    pub code: String,
579    pub message: String,
580    pub causes: Vec<SingleFederationError>,
581}
582
583impl Display for AggregateFederationError {
584    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
585        write!(f, "[{}] {}\nCaused by:", self.code, self.message)?;
586        for error in &self.causes {
587            write!(f, "\n\n  - ")?;
588            for c in error.to_string().chars() {
589                if c == '\n' {
590                    write!(f, "\n    ")?;
591                } else {
592                    f.write_char(c)?;
593                }
594            }
595        }
596        Ok(())
597    }
598}
599
600// PORT_NOTE: Often times, JS functions would either throw/return a GraphQLError, return a vector
601// of GraphQLErrors, or take a vector of GraphQLErrors and group them together under an
602// AggregateGraphQLError which itself would have a specific error message and code, and throw that.
603// We represent all these cases with an enum, and delegate to the members.
604#[derive(Clone, thiserror::Error)]
605pub enum FederationError {
606    #[error(transparent)]
607    SingleFederationError(#[from] SingleFederationError),
608    #[error(transparent)]
609    MultipleFederationErrors(#[from] MultipleFederationErrors),
610    #[error(transparent)]
611    AggregateFederationError(#[from] AggregateFederationError),
612}
613
614impl std::fmt::Debug for FederationError {
615    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
616        match self {
617            Self::SingleFederationError(inner) => std::fmt::Debug::fmt(inner, f),
618            Self::MultipleFederationErrors(inner) => std::fmt::Debug::fmt(inner, f),
619            Self::AggregateFederationError(inner) => std::fmt::Debug::fmt(inner, f),
620        }
621    }
622}
623
624impl From<DiagnosticList> for FederationError {
625    fn from(value: DiagnosticList) -> Self {
626        SingleFederationError::from(value).into()
627    }
628}
629
630impl<T> From<WithErrors<T>> for FederationError {
631    fn from(value: WithErrors<T>) -> Self {
632        value.errors.into()
633    }
634}
635
636impl FederationError {
637    pub fn internal(message: impl Into<String>) -> Self {
638        SingleFederationError::Internal {
639            message: message.into(),
640        }
641        .into()
642    }
643}
644
645impl MultipleFederationErrors {
646    /// Converts into `Result<(), FederationError>`.
647    /// - The return value can be either Ok, Err with a SingleFederationError or MultipleFederationErrors,
648    ///   depending on the number of errors in the input.
649    pub fn into_result(self) -> Result<(), FederationError> {
650        match self.errors.len().cmp(&1) {
651            Ordering::Less => Ok(()),
652            Ordering::Equal => Err(self.errors[0].clone().into()),
653            Ordering::Greater => Err(self.into()),
654        }
655    }
656}
657
658// We didn't track errors addition precisely pre-2.0 and tracking it now has an unclear ROI, so we
659// just mark all the error code that predates 2.0 as 0.x.
660const FED1_CODE: &str = "0.x";
661
662#[derive(Debug, Clone)]
663pub struct ErrorCodeMetadata {
664    pub added_in: &'static str,
665    pub replaces: &'static [&'static str],
666}
667
668#[derive(Debug)]
669pub struct ErrorCodeDefinition {
670    code: String,
671    // PORT_NOTE: Known as "description" in the JS code. The name was changed to distinguish it from
672    // Error.description().
673    doc_description: String,
674    metadata: ErrorCodeMetadata,
675}
676
677impl ErrorCodeDefinition {
678    fn new(code: String, doc_description: String, metadata: Option<ErrorCodeMetadata>) -> Self {
679        Self {
680            code,
681            doc_description,
682            metadata: metadata.unwrap_or_else(|| DEFAULT_METADATA.clone()),
683        }
684    }
685
686    pub fn code(&self) -> &str {
687        &self.code
688    }
689
690    pub fn doc_description(&self) -> &str {
691        &self.doc_description
692    }
693
694    pub fn metadata(&self) -> &ErrorCodeMetadata {
695        &self.metadata
696    }
697}
698
699/*
700 * Most codes currently originate from the initial fed 2 release so we use this for convenience.
701 * This can be changed later, inline versions everywhere, if that becomes irrelevant.
702 */
703static DEFAULT_METADATA: ErrorCodeMetadata = ErrorCodeMetadata {
704    added_in: "2.0.0",
705    replaces: &[],
706};
707
708struct ErrorCodeCategory<TElement: Clone + Into<String>> {
709    // Fn(element: TElement) -> String
710    extract_code: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
711    // Fn(element: TElement) -> String
712    make_doc_description: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
713    metadata: ErrorCodeMetadata,
714}
715
716impl<TElement: Clone + Into<String>> ErrorCodeCategory<TElement> {
717    fn new(
718        extract_code: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
719        make_doc_description: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
720        metadata: Option<ErrorCodeMetadata>,
721    ) -> Self {
722        Self {
723            extract_code,
724            make_doc_description,
725            metadata: metadata.unwrap_or_else(|| DEFAULT_METADATA.clone()),
726        }
727    }
728
729    // PORT_NOTE: The Typescript type in the JS code only has get(), but I also added createCode()
730    // here since it's used in the return type of makeErrorCodeCategory().
731    fn create_code(&self, element: TElement) -> ErrorCodeDefinition {
732        ErrorCodeDefinition::new(
733            (self.extract_code)(element.clone()),
734            (self.make_doc_description)(element),
735            Some(self.metadata.clone()),
736        )
737    }
738}
739
740impl ErrorCodeCategory<String> {
741    fn new_federation_directive(
742        code_suffix: String,
743        make_doc_description: Box<dyn 'static + Send + Sync + Fn(String) -> String>,
744        metadata: Option<ErrorCodeMetadata>,
745    ) -> Self {
746        Self::new(
747            Box::new(move |element: String| format!("{}_{}", element.to_uppercase(), code_suffix)),
748            make_doc_description,
749            metadata,
750        )
751    }
752}
753
754static INVALID_GRAPHQL: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
755    ErrorCodeDefinition::new(
756        "INVALID_GRAPHQL".to_owned(),
757        "A schema is invalid GraphQL: it violates one of the rule of the specification.".to_owned(),
758        None,
759    )
760});
761static DIRECTIVE_DEFINITION_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
762    ErrorCodeDefinition::new(
763        "DIRECTIVE_DEFINITION_INVALID".to_owned(),
764        "A built-in or federation directive has an invalid definition in the schema.".to_owned(),
765        Some(ErrorCodeMetadata {
766            replaces: &["TAG_DEFINITION_INVALID"],
767            ..DEFAULT_METADATA.clone()
768        }),
769    )
770});
771
772static TYPE_DEFINITION_INVALID: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
773    ErrorCodeDefinition::new(
774        "TYPE_DEFINITION_INVALID".to_owned(),
775        "A built-in or federation type has an invalid definition in the schema.".to_owned(),
776        None,
777    )
778});
779
780static UNSUPPORTED_LINKED_FEATURE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
781    ErrorCodeDefinition::new(
782        "UNSUPPORTED_LINKED_FEATURE".to_owned(),
783        "Indicates that a feature used in a @link is either unsupported or is used with unsupported options.".to_owned(),
784        None,
785    )
786});
787
788static UNKNOWN_FEDERATION_LINK_VERSION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
789    ErrorCodeDefinition::new(
790        "UNKNOWN_FEDERATION_LINK_VERSION".to_owned(),
791        "The version of federation in a @link directive on the schema is unknown.".to_owned(),
792        None,
793    )
794});
795
796static UNKNOWN_LINK_VERSION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
797    ErrorCodeDefinition::new(
798        "UNKNOWN_LINK_VERSION".to_owned(),
799        "The version of @link set on the schema is unknown.".to_owned(),
800        Some(ErrorCodeMetadata {
801            added_in: "2.1.0",
802            replaces: &[],
803        }),
804    )
805});
806
807static FIELDS_HAS_ARGS: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
808    ErrorCodeCategory::new_federation_directive(
809        "FIELDS_HAS_ARGS".to_owned(),
810        Box::new(|directive| {
811            format!(
812                "The `fields` argument of a `@{}` directive includes a field defined with arguments (which is not currently supported).",
813                directive
814            )
815        }),
816        None,
817    )
818});
819
820static KEY_FIELDS_HAS_ARGS: LazyLock<ErrorCodeDefinition> =
821    LazyLock::new(|| FIELDS_HAS_ARGS.create_code("key".to_owned()));
822
823static PROVIDES_FIELDS_HAS_ARGS: LazyLock<ErrorCodeDefinition> =
824    LazyLock::new(|| FIELDS_HAS_ARGS.create_code("provides".to_owned()));
825
826static DIRECTIVE_FIELDS_MISSING_EXTERNAL: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(
827    || {
828        ErrorCodeCategory::new_federation_directive(
829            "FIELDS_MISSING_EXTERNAL".to_owned(),
830            Box::new(|directive| {
831                format!(
832                    "The `fields` argument of a `@{}` directive includes a field that is not marked as `@external`.",
833                    directive
834                )
835            }),
836            Some(ErrorCodeMetadata {
837                added_in: FED1_CODE,
838                replaces: &[],
839            }),
840        )
841    },
842);
843
844static PROVIDES_FIELDS_MISSING_EXTERNAL: LazyLock<ErrorCodeDefinition> =
845    LazyLock::new(|| DIRECTIVE_FIELDS_MISSING_EXTERNAL.create_code("provides".to_owned()));
846static REQUIRES_FIELDS_MISSING_EXTERNAL: LazyLock<ErrorCodeDefinition> =
847    LazyLock::new(|| DIRECTIVE_FIELDS_MISSING_EXTERNAL.create_code("requires".to_owned()));
848
849static DIRECTIVE_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeCategory<String>> =
850    LazyLock::new(|| {
851        ErrorCodeCategory::new_federation_directive(
852            "UNSUPPORTED_ON_INTERFACE".to_owned(),
853            Box::new(|directive| {
854                let suffix = if directive == "key" {
855                    "only supported when @linking to federation 2.3+"
856                } else {
857                    "not (yet) supported"
858                };
859                format!(
860                    "A `@{}` directive is used on an interface, which is {}.",
861                    directive, suffix
862                )
863            }),
864            None,
865        )
866    });
867
868static KEY_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeDefinition> =
869    LazyLock::new(|| DIRECTIVE_UNSUPPORTED_ON_INTERFACE.create_code("key".to_owned()));
870static PROVIDES_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeDefinition> =
871    LazyLock::new(|| DIRECTIVE_UNSUPPORTED_ON_INTERFACE.create_code("provides".to_owned()));
872static REQUIRES_UNSUPPORTED_ON_INTERFACE: LazyLock<ErrorCodeDefinition> =
873    LazyLock::new(|| DIRECTIVE_UNSUPPORTED_ON_INTERFACE.create_code("requires".to_owned()));
874
875static DIRECTIVE_IN_FIELDS_ARG: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
876    ErrorCodeCategory::new_federation_directive(
877        "DIRECTIVE_IN_FIELDS_ARG".to_owned(),
878        Box::new(|directive| {
879            format!(
880                "The `fields` argument of a `@{}` directive includes some directive applications. This is not supported",
881                directive
882            )
883        }),
884        Some(ErrorCodeMetadata {
885            added_in: "2.1.0",
886            replaces: &[],
887        }),
888    )
889});
890
891static KEY_DIRECTIVE_IN_FIELDS_ARGS: LazyLock<ErrorCodeDefinition> =
892    LazyLock::new(|| DIRECTIVE_IN_FIELDS_ARG.create_code("key".to_owned()));
893static PROVIDES_DIRECTIVE_IN_FIELDS_ARGS: LazyLock<ErrorCodeDefinition> =
894    LazyLock::new(|| DIRECTIVE_IN_FIELDS_ARG.create_code("provides".to_owned()));
895static REQUIRES_DIRECTIVE_IN_FIELDS_ARGS: LazyLock<ErrorCodeDefinition> =
896    LazyLock::new(|| DIRECTIVE_IN_FIELDS_ARG.create_code("requires".to_owned()));
897
898static EXTERNAL_UNUSED: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
899    ErrorCodeDefinition::new(
900        "EXTERNAL_UNUSED".to_owned(),
901        "An `@external` field is not being used by any instance of `@key`, `@requires`, `@provides` or to satisfy an interface implementation.".to_owned(),
902        Some(ErrorCodeMetadata {
903            added_in: FED1_CODE,
904            replaces: &[],
905        }),
906)
907});
908
909static TYPE_WITH_ONLY_UNUSED_EXTERNAL: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
910    ErrorCodeDefinition::new(
911        "TYPE_WITH_ONLY_UNUSED_EXTERNAL".to_owned(),
912        [
913            "A federation 1 schema has a composite type comprised only of unused external fields.".to_owned(),
914            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),
915            "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()
916        ].join(" "),
917        None,
918)
919});
920
921static PROVIDES_ON_NON_OBJECT_FIELD: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
922    ErrorCodeDefinition::new(
923        "PROVIDES_ON_NON_OBJECT_FIELD".to_owned(),
924        "A `@provides` directive is used to mark a field whose base type is not an object type."
925            .to_owned(),
926        None,
927    )
928});
929
930static DIRECTIVE_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
931    ErrorCodeCategory::new_federation_directive(
932        "INVALID_FIELDS_TYPE".to_owned(),
933        Box::new(|directive| {
934            format!(
935                "The value passed to the `fields` argument of a `@{}` directive is not a string.",
936                directive
937            )
938        }),
939        None,
940    )
941});
942
943static KEY_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeDefinition> =
944    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS_TYPE.create_code("key".to_owned()));
945static PROVIDES_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeDefinition> =
946    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS_TYPE.create_code("provides".to_owned()));
947static REQUIRES_INVALID_FIELDS_TYPE: LazyLock<ErrorCodeDefinition> =
948    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS_TYPE.create_code("requires".to_owned()));
949
950static DIRECTIVE_INVALID_FIELDS: LazyLock<ErrorCodeCategory<String>> = LazyLock::new(|| {
951    ErrorCodeCategory::new_federation_directive(
952        "INVALID_FIELDS".to_owned(),
953        Box::new(|directive| {
954            format!(
955                "The `fields` argument of a `@{}` directive is invalid (it has invalid syntax, includes unknown fields, ...).",
956                directive
957            )
958        }),
959        None,
960    )
961});
962
963static KEY_INVALID_FIELDS: LazyLock<ErrorCodeDefinition> =
964    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS.create_code("key".to_owned()));
965static PROVIDES_INVALID_FIELDS: LazyLock<ErrorCodeDefinition> =
966    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS.create_code("provides".to_owned()));
967static REQUIRES_INVALID_FIELDS: LazyLock<ErrorCodeDefinition> =
968    LazyLock::new(|| DIRECTIVE_INVALID_FIELDS.create_code("requires".to_owned()));
969
970static KEY_FIELDS_SELECT_INVALID_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
971    ErrorCodeDefinition::new(
972        "KEY_FIELDS_SELECT_INVALID_TYPE".to_owned(),
973        "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(),
974        Some(ErrorCodeMetadata {
975            added_in: FED1_CODE,
976            replaces: &[],
977        }),
978)
979});
980
981static ROOT_TYPE_USED: LazyLock<ErrorCodeCategory<SchemaRootKind>> = LazyLock::new(|| {
982    ErrorCodeCategory::new(
983        Box::new(|element| {
984            let kind: String = element.into();
985            format!("ROOT_{}_USED", kind.to_uppercase())
986        }),
987        Box::new(|element| {
988            let kind: String = element.into();
989            format!(
990                "A subgraph's schema defines a type with the name `{}`, while also specifying a _different_ type name as the root query object. This is not allowed.",
991                kind
992            )
993        }),
994        Some(ErrorCodeMetadata {
995            added_in: FED1_CODE,
996            replaces: &[],
997        }),
998    )
999});
1000
1001static ROOT_QUERY_USED: LazyLock<ErrorCodeDefinition> =
1002    LazyLock::new(|| ROOT_TYPE_USED.create_code(SchemaRootKind::Query));
1003static ROOT_MUTATION_USED: LazyLock<ErrorCodeDefinition> =
1004    LazyLock::new(|| ROOT_TYPE_USED.create_code(SchemaRootKind::Mutation));
1005static ROOT_SUBSCRIPTION_USED: LazyLock<ErrorCodeDefinition> =
1006    LazyLock::new(|| ROOT_TYPE_USED.create_code(SchemaRootKind::Subscription));
1007
1008static INVALID_SUBGRAPH_NAME: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1009    ErrorCodeDefinition::new(
1010        "INVALID_SUBGRAPH_NAME".to_owned(),
1011        "A subgraph name is invalid (subgraph names cannot be a single underscore (\"_\"))."
1012            .to_owned(),
1013        None,
1014    )
1015});
1016
1017static NO_QUERIES: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1018    ErrorCodeDefinition::new(
1019        "NO_QUERIES".to_owned(),
1020        "None of the composed subgraphs expose any query.".to_owned(),
1021        None,
1022    )
1023});
1024
1025static INTERFACE_FIELD_NO_IMPLEM: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1026    ErrorCodeDefinition::new(
1027        "INTERFACE_FIELD_NO_IMPLEM".to_owned(),
1028        "After subgraph merging, an implementation is missing a field of one of the interface it implements (which can happen for valid subgraphs).".to_owned(),
1029        None,
1030    )
1031});
1032
1033static TYPE_KIND_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1034    ErrorCodeDefinition::new(
1035        "TYPE_KIND_MISMATCH".to_owned(),
1036        "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(),
1037        Some(ErrorCodeMetadata {
1038            replaces: &["VALUE_TYPE_KIND_MISMATCH", "EXTENSION_OF_WRONG_KIND", "ENUM_MISMATCH_TYPE"],
1039            ..DEFAULT_METADATA.clone()
1040        }),
1041    )
1042});
1043
1044static EXTERNAL_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1045    ErrorCodeDefinition::new(
1046        "EXTERNAL_TYPE_MISMATCH".to_owned(),
1047        "An `@external` field has a type that is incompatible with the declaration(s) of that field in other subgraphs.".to_owned(),
1048        Some(ErrorCodeMetadata {
1049            added_in: FED1_CODE,
1050            replaces: &[],
1051        }),
1052    )
1053});
1054
1055static EXTERNAL_COLLISION_WITH_ANOTHER_DIRECTIVE: LazyLock<ErrorCodeDefinition> =
1056    LazyLock::new(|| {
1057        ErrorCodeDefinition::new(
1058            "EXTERNAL_COLLISION_WITH_ANOTHER_DIRECTIVE".to_owned(),
1059            "The @external directive collides with other directives in some situations.".to_owned(),
1060            Some(ErrorCodeMetadata {
1061                added_in: "2.1.0",
1062                replaces: &[],
1063            }),
1064        )
1065    });
1066
1067static EXTERNAL_ARGUMENT_MISSING: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1068    ErrorCodeDefinition::new(
1069        "EXTERNAL_ARGUMENT_MISSING".to_owned(),
1070        "An `@external` field is missing some arguments present in the declaration(s) of that field in other subgraphs.".to_owned(),
1071        None,
1072    )
1073});
1074
1075static EXTERNAL_ARGUMENT_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1076    ErrorCodeDefinition::new(
1077        "EXTERNAL_ARGUMENT_TYPE_MISMATCH".to_owned(),
1078        "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(),
1079        None,
1080    )
1081});
1082
1083static EXTERNAL_ARGUMENT_DEFAULT_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1084    ErrorCodeDefinition::new(
1085        "EXTERNAL_ARGUMENT_DEFAULT_MISMATCH".to_owned(),
1086        "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(),
1087        None,
1088    )
1089});
1090
1091static EXTERNAL_ON_INTERFACE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1092    ErrorCodeDefinition::new(
1093        "EXTERNAL_ON_INTERFACE".to_owned(),
1094        "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(),
1095        None,
1096    )
1097});
1098
1099static MERGED_DIRECTIVE_APPLICATION_ON_EXTERNAL: LazyLock<ErrorCodeDefinition> = LazyLock::new(
1100    || {
1101        ErrorCodeDefinition::new(
1102        "MERGED_DIRECTIVE_APPLICATION_ON_EXTERNAL".to_owned(),
1103        "In a subgraph, a field is both marked @external and has a merged directive applied to it".to_owned(),
1104        None,
1105    )
1106    },
1107);
1108
1109static FIELD_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1110    ErrorCodeDefinition::new(
1111        "FIELD_TYPE_MISMATCH".to_owned(),
1112        "A field has a type that is incompatible with other declarations of that field in other subgraphs.".to_owned(),
1113        Some(ErrorCodeMetadata {
1114            replaces: &["VALUE_TYPE_FIELD_TYPE_MISMATCH"],
1115            ..DEFAULT_METADATA.clone()
1116        }),
1117    )
1118});
1119
1120static FIELD_ARGUMENT_TYPE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1121    ErrorCodeDefinition::new(
1122        "FIELD_ARGUMENT_TYPE_MISMATCH".to_owned(),
1123        "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(),
1124        Some(ErrorCodeMetadata {
1125            replaces: &["VALUE_TYPE_INPUT_VALUE_MISMATCH"],
1126            ..DEFAULT_METADATA.clone()
1127        }),
1128    )
1129});
1130
1131static INPUT_FIELD_DEFAULT_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1132    ErrorCodeDefinition::new(
1133        "INPUT_FIELD_DEFAULT_MISMATCH".to_owned(),
1134        "An input field has a default value that is incompatible with other declarations of that field in other subgraphs.".to_owned(),
1135        None,
1136    )
1137});
1138
1139static FIELD_ARGUMENT_DEFAULT_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1140    ErrorCodeDefinition::new(
1141        "FIELD_ARGUMENT_DEFAULT_MISMATCH".to_owned(),
1142        "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(),
1143        None,
1144    )
1145});
1146
1147static EXTENSION_WITH_NO_BASE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1148    ErrorCodeDefinition::new(
1149        "EXTENSION_WITH_NO_BASE".to_owned(),
1150        "A subgraph is attempting to `extend` a type that is not originally defined in any known subgraph.".to_owned(),
1151        Some(ErrorCodeMetadata {
1152            added_in: FED1_CODE,
1153            replaces: &[],
1154        }),
1155    )
1156});
1157
1158static EXTERNAL_MISSING_ON_BASE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1159    ErrorCodeDefinition::new(
1160        "EXTERNAL_MISSING_ON_BASE".to_owned(),
1161        "A field is marked as `@external` in a subgraph but with no non-external declaration in any other subgraph.".to_owned(),
1162        Some(ErrorCodeMetadata {
1163            added_in: FED1_CODE,
1164            replaces: &[],
1165        }),
1166    )
1167});
1168
1169static INVALID_FIELD_SHARING: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1170    ErrorCodeDefinition::new(
1171        "INVALID_FIELD_SHARING".to_owned(),
1172        "A field that is non-shareable in at least one subgraph is resolved by multiple subgraphs."
1173            .to_owned(),
1174        None,
1175    )
1176});
1177
1178static INVALID_SHAREABLE_USAGE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1179    ErrorCodeDefinition::new(
1180        "INVALID_SHAREABLE_USAGE".to_owned(),
1181        "The `@shareable` federation directive is used in an invalid way.".to_owned(),
1182        Some(ErrorCodeMetadata {
1183            added_in: "2.1.2",
1184            replaces: &[],
1185        }),
1186    )
1187});
1188
1189static INVALID_LINK_DIRECTIVE_USAGE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1190    ErrorCodeDefinition::new(
1191        "INVALID_LINK_DIRECTIVE_USAGE".to_owned(),
1192        "An application of the @link directive is invalid/does not respect the specification."
1193            .to_owned(),
1194        None,
1195    )
1196});
1197
1198static INVALID_LINK_IDENTIFIER: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1199    ErrorCodeDefinition::new(
1200        "INVALID_LINK_IDENTIFIER".to_owned(),
1201        "A url/version for a @link feature is invalid/does not respect the specification."
1202            .to_owned(),
1203        Some(ErrorCodeMetadata {
1204            added_in: "2.1.0",
1205            replaces: &[],
1206        }),
1207    )
1208});
1209
1210static LINK_IMPORT_NAME_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1211    ErrorCodeDefinition::new(
1212        "LINK_IMPORT_NAME_MISMATCH".to_owned(),
1213        "The import name for a merged directive (as declared by the relevant `@link(import:)` argument) is inconsistent between subgraphs.".to_owned(),
1214        None,
1215    )
1216});
1217
1218static REFERENCED_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1219    ErrorCodeDefinition::new(
1220        "REFERENCED_INACCESSIBLE".to_owned(),
1221        "An element is marked as @inaccessible but is referenced by an element visible in the API schema.".to_owned(),
1222        None,
1223    )
1224});
1225
1226static DEFAULT_VALUE_USES_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1227    ErrorCodeDefinition::new(
1228        "DEFAULT_VALUE_USES_INACCESSIBLE".to_owned(),
1229        "An element is marked as @inaccessible but is used in the default value of an element visible in the API schema.".to_owned(),
1230        None,
1231    )
1232});
1233
1234static QUERY_ROOT_TYPE_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1235    ErrorCodeDefinition::new(
1236        "QUERY_ROOT_TYPE_INACCESSIBLE".to_owned(),
1237        "An element is marked as @inaccessible but is the query root type, which must be visible in the API schema.".to_owned(),
1238        None,
1239    )
1240});
1241
1242static REQUIRED_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1243    ErrorCodeDefinition::new(
1244        "REQUIRED_INACCESSIBLE".to_owned(),
1245        "An element is marked as @inaccessible but is required by an element visible in the API schema.".to_owned(),
1246        None,
1247    )
1248});
1249
1250static IMPLEMENTED_BY_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1251    ErrorCodeDefinition::new(
1252        "IMPLEMENTED_BY_INACCESSIBLE".to_owned(),
1253        "An element is marked as @inaccessible but implements an element visible in the API schema.".to_owned(),
1254        None,
1255    )
1256});
1257
1258static DISALLOWED_INACCESSIBLE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1259    ErrorCodeDefinition::new(
1260        "DISALLOWED_INACCESSIBLE".to_owned(),
1261        "An element is marked as @inaccessible that is not allowed to be @inaccessible.".to_owned(),
1262        None,
1263    )
1264});
1265
1266static ONLY_INACCESSIBLE_CHILDREN: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1267    ErrorCodeDefinition::new(
1268        "ONLY_INACCESSIBLE_CHILDREN".to_owned(),
1269        "A type visible in the API schema has only @inaccessible children.".to_owned(),
1270        None,
1271    )
1272});
1273
1274static REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH: LazyLock<ErrorCodeDefinition> = LazyLock::new(
1275    || {
1276        ErrorCodeDefinition::new(
1277        "REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH".to_owned(),
1278        "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(),
1279        None,
1280    )
1281    },
1282);
1283
1284static REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH: LazyLock<ErrorCodeDefinition> = LazyLock::new(
1285    || {
1286        ErrorCodeDefinition::new(
1287        "REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH".to_owned(),
1288        "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(),
1289        None,
1290    )
1291    },
1292);
1293
1294static EMPTY_MERGED_INPUT_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1295    ErrorCodeDefinition::new(
1296        "EMPTY_MERGED_INPUT_TYPE".to_owned(),
1297        "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(),
1298        None,
1299    )
1300});
1301
1302static ENUM_VALUE_MISMATCH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1303    ErrorCodeDefinition::new(
1304        "ENUM_VALUE_MISMATCH".to_owned(),
1305        "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(),
1306        None,
1307    )
1308});
1309
1310static EMPTY_MERGED_ENUM_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1311    ErrorCodeDefinition::new(
1312        "EMPTY_MERGED_ENUM_TYPE".to_owned(),
1313        "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(),
1314        None,
1315    )
1316});
1317
1318static SHAREABLE_HAS_MISMATCHED_RUNTIME_TYPES: LazyLock<ErrorCodeDefinition> = LazyLock::new(
1319    || {
1320        ErrorCodeDefinition::new(
1321        "SHAREABLE_HAS_MISMATCHED_RUNTIME_TYPES".to_owned(),
1322        "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(),
1323        None,
1324    )
1325    },
1326);
1327
1328static SATISFIABILITY_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1329    ErrorCodeDefinition::new(
1330        "SATISFIABILITY_ERROR".to_owned(),
1331        "Subgraphs can be merged, but the resulting supergraph API would have queries that cannot be satisfied by those subgraphs.".to_owned(),
1332        None,
1333    )
1334});
1335
1336static OVERRIDE_FROM_SELF_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1337    ErrorCodeDefinition::new(
1338        "OVERRIDE_FROM_SELF_ERROR".to_owned(),
1339        "Field with `@override` directive has \"from\" location that references its own subgraph."
1340            .to_owned(),
1341        None,
1342    )
1343});
1344
1345static OVERRIDE_SOURCE_HAS_OVERRIDE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1346    ErrorCodeDefinition::new(
1347        "OVERRIDE_SOURCE_HAS_OVERRIDE".to_owned(),
1348        "Field which is overridden to another subgraph is also marked @override.".to_owned(),
1349        None,
1350    )
1351});
1352
1353static OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE: LazyLock<ErrorCodeDefinition> = LazyLock::new(
1354    || {
1355        ErrorCodeDefinition::new(
1356        "OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE".to_owned(),
1357        "The @override directive cannot be used on external fields, nor to override fields with either @external, @provides, or @requires.".to_owned(),
1358        None,
1359    )
1360    },
1361);
1362
1363static OVERRIDE_ON_INTERFACE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1364    ErrorCodeDefinition::new(
1365        "OVERRIDE_ON_INTERFACE".to_owned(),
1366        "The @override directive cannot be used on the fields of an interface type.".to_owned(),
1367        Some(ErrorCodeMetadata {
1368            added_in: "2.3.0",
1369            replaces: &[],
1370        }),
1371    )
1372});
1373
1374static UNSUPPORTED_FEATURE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1375    ErrorCodeDefinition::new(
1376        "UNSUPPORTED_FEATURE".to_owned(),
1377        "Indicates an error due to feature currently unsupported by federation.".to_owned(),
1378        Some(ErrorCodeMetadata {
1379            added_in: "2.1.0",
1380            replaces: &[],
1381        }),
1382    )
1383});
1384
1385static INVALID_FEDERATION_SUPERGRAPH: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1386    ErrorCodeDefinition::new(
1387        "INVALID_FEDERATION_SUPERGRAPH".to_owned(),
1388        "Indicates that a schema provided for an Apollo Federation supergraph is not a valid supergraph schema.".to_owned(),
1389        Some(ErrorCodeMetadata {
1390            added_in: "2.1.0",
1391            replaces: &[],
1392        }),
1393    )
1394});
1395
1396static DOWNSTREAM_SERVICE_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1397    ErrorCodeDefinition::new(
1398        "DOWNSTREAM_SERVICE_ERROR".to_owned(),
1399        "Indicates an error in a subgraph service query during query execution in a federated service.".to_owned(),
1400        Some(ErrorCodeMetadata {
1401            added_in: FED1_CODE,
1402            replaces: &[],
1403        }),
1404    )
1405});
1406
1407static DIRECTIVE_COMPOSITION_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1408    ErrorCodeDefinition::new(
1409        "DIRECTIVE_COMPOSITION_ERROR".to_owned(),
1410        "Error when composing custom directives.".to_owned(),
1411        Some(ErrorCodeMetadata {
1412            added_in: "2.1.0",
1413            replaces: &[],
1414        }),
1415    )
1416});
1417
1418static INTERFACE_OBJECT_USAGE_ERROR: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1419    ErrorCodeDefinition::new(
1420        "INTERFACE_OBJECT_USAGE_ERROR".to_owned(),
1421        "Error in the usage of the @interfaceObject directive.".to_owned(),
1422        Some(ErrorCodeMetadata {
1423            added_in: "2.3.0",
1424            replaces: &[],
1425        }),
1426    )
1427});
1428
1429static INTERFACE_KEY_NOT_ON_IMPLEMENTATION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1430    ErrorCodeDefinition::new(
1431        "INTERFACE_KEY_NOT_ON_IMPLEMENTATION".to_owned(),
1432        "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(),
1433        Some(ErrorCodeMetadata {
1434            added_in: "2.3.0",
1435            replaces: &[],
1436        }),
1437    )
1438});
1439
1440static INTERFACE_KEY_MISSING_IMPLEMENTATION_TYPE: LazyLock<ErrorCodeDefinition> = LazyLock::new(
1441    || {
1442        ErrorCodeDefinition::new(
1443        "INTERFACE_KEY_MISSING_IMPLEMENTATION_TYPE".to_owned(),
1444        "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(),
1445        Some(ErrorCodeMetadata {
1446            added_in: "2.3.0",
1447            replaces: &[],
1448        }),
1449    )
1450    },
1451);
1452
1453static INTERNAL: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1454    ErrorCodeDefinition::new(
1455        "INTERNAL".to_owned(),
1456        "An internal federation error occured.".to_owned(),
1457        None,
1458    )
1459});
1460
1461static UNSUPPORTED_FEDERATION_VERSION: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1462    ErrorCodeDefinition::new(
1463        "UNSUPPORTED_FEDERATION_VERSION".to_owned(),
1464        "Supergraphs composed with federation version 1 are not supported. Please recompose your supergraph with federation version 2 or greater".to_owned(),
1465        None,
1466    )
1467});
1468
1469static UNSUPPORTED_FEDERATION_DIRECTIVE: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1470    ErrorCodeDefinition::new(
1471        "UNSUPPORTED_FEDERATION_DIRECTIVE".to_owned(),
1472        "Indicates that the specified specification version is outside of supported range"
1473            .to_owned(),
1474        None,
1475    )
1476});
1477
1478static QUERY_PLAN_COMPLEXITY_EXCEEDED: LazyLock<ErrorCodeDefinition> = LazyLock::new(|| {
1479    ErrorCodeDefinition::new(
1480        "QUERY_PLAN_COMPLEXITY_EXCEEDED".to_owned(),
1481        "Indicates that provided query has too many possible ways to generate a plan and cannot be planned in a reasonable amount of time"
1482            .to_owned(),
1483        None,
1484    )
1485});
1486
1487#[derive(Debug, strum_macros::EnumIter)]
1488pub enum ErrorCode {
1489    Internal,
1490    InvalidGraphQL,
1491    DirectiveDefinitionInvalid,
1492    TypeDefinitionInvalid,
1493    UnsupportedLinkedFeature,
1494    UnknownFederationLinkVersion,
1495    UnknownLinkVersion,
1496    KeyFieldsHasArgs,
1497    ProvidesFieldsHasArgs,
1498    ProvidesFieldsMissingExternal,
1499    RequiresFieldsMissingExternal,
1500    KeyUnsupportedOnInterface,
1501    ProvidesUnsupportedOnInterface,
1502    RequiresUnsupportedOnInterface,
1503    KeyDirectiveInFieldsArgs,
1504    ProvidesDirectiveInFieldsArgs,
1505    RequiresDirectiveInFieldsArgs,
1506    ExternalUnused,
1507    TypeWithOnlyUnusedExternal,
1508    ProvidesOnNonObjectField,
1509    KeyInvalidFieldsType,
1510    ProvidesInvalidFieldsType,
1511    RequiresInvalidFieldsType,
1512    KeyInvalidFields,
1513    ProvidesInvalidFields,
1514    RequiresInvalidFields,
1515    KeyFieldsSelectInvalidType,
1516    RootQueryUsed,
1517    RootMutationUsed,
1518    RootSubscriptionUsed,
1519    InvalidSubgraphName,
1520    NoQueries,
1521    InterfaceFieldNoImplem,
1522    TypeKindMismatch,
1523    ExternalTypeMismatch,
1524    ExternalCollisionWithAnotherDirective,
1525    ExternalArgumentMissing,
1526    ExternalArgumentTypeMismatch,
1527    ExternalArgumentDefaultMismatch,
1528    ExternalOnInterface,
1529    MergedDirectiveApplicationOnExternal,
1530    FieldTypeMismatch,
1531    FieldArgumentTypeMismatch,
1532    InputFieldDefaultMismatch,
1533    FieldArgumentDefaultMismatch,
1534    ExtensionWithNoBase,
1535    ExternalMissingOnBase,
1536    InvalidFieldSharing,
1537    InvalidShareableUsage,
1538    InvalidLinkDirectiveUsage,
1539    InvalidLinkIdentifier,
1540    LinkImportNameMismatch,
1541    ReferencedInaccessible,
1542    DefaultValueUsesInaccessible,
1543    QueryRootTypeInaccessible,
1544    RequiredInaccessible,
1545    ImplementedByInaccessible,
1546    DisallowedInaccessible,
1547    OnlyInaccessibleChildren,
1548    RequiredInputFieldMissingInSomeSubgraph,
1549    RequiredArgumentMissingInSomeSubgraph,
1550    EmptyMergedInputType,
1551    EnumValueMismatch,
1552    EmptyMergedEnumType,
1553    ShareableHasMismatchedRuntimeTypes,
1554    SatisfiabilityError,
1555    OverrideFromSelfError,
1556    OverrideSourceHasOverride,
1557    OverrideCollisionWithAnotherDirective,
1558    OverrideOnInterface,
1559    UnsupportedFeature,
1560    InvalidFederationSupergraph,
1561    DownstreamServiceError,
1562    DirectiveCompositionError,
1563    InterfaceObjectUsageError,
1564    InterfaceKeyNotOnImplementation,
1565    InterfaceKeyMissingImplementationType,
1566    UnsupportedFederationVersion,
1567    UnsupportedFederationDirective,
1568    QueryPlanComplexityExceededError,
1569}
1570
1571impl ErrorCode {
1572    pub fn definition(&self) -> &'static ErrorCodeDefinition {
1573        match self {
1574            // TODO: We should determine the code and doc info for internal errors.
1575            ErrorCode::Internal => &INTERNAL,
1576            ErrorCode::InvalidGraphQL => &INVALID_GRAPHQL,
1577            ErrorCode::DirectiveDefinitionInvalid => &DIRECTIVE_DEFINITION_INVALID,
1578            ErrorCode::TypeDefinitionInvalid => &TYPE_DEFINITION_INVALID,
1579            ErrorCode::UnsupportedLinkedFeature => &UNSUPPORTED_LINKED_FEATURE,
1580            ErrorCode::UnknownFederationLinkVersion => &UNKNOWN_FEDERATION_LINK_VERSION,
1581            ErrorCode::UnknownLinkVersion => &UNKNOWN_LINK_VERSION,
1582            ErrorCode::KeyFieldsHasArgs => &KEY_FIELDS_HAS_ARGS,
1583            ErrorCode::ProvidesFieldsHasArgs => &PROVIDES_FIELDS_HAS_ARGS,
1584            ErrorCode::ProvidesFieldsMissingExternal => &PROVIDES_FIELDS_MISSING_EXTERNAL,
1585            ErrorCode::RequiresFieldsMissingExternal => &REQUIRES_FIELDS_MISSING_EXTERNAL,
1586            ErrorCode::KeyUnsupportedOnInterface => &KEY_UNSUPPORTED_ON_INTERFACE,
1587            ErrorCode::ProvidesUnsupportedOnInterface => &PROVIDES_UNSUPPORTED_ON_INTERFACE,
1588            ErrorCode::RequiresUnsupportedOnInterface => &REQUIRES_UNSUPPORTED_ON_INTERFACE,
1589            ErrorCode::KeyDirectiveInFieldsArgs => &KEY_DIRECTIVE_IN_FIELDS_ARGS,
1590            ErrorCode::ProvidesDirectiveInFieldsArgs => &PROVIDES_DIRECTIVE_IN_FIELDS_ARGS,
1591            ErrorCode::RequiresDirectiveInFieldsArgs => &REQUIRES_DIRECTIVE_IN_FIELDS_ARGS,
1592            ErrorCode::ExternalUnused => &EXTERNAL_UNUSED,
1593            ErrorCode::ExternalCollisionWithAnotherDirective => {
1594                &EXTERNAL_COLLISION_WITH_ANOTHER_DIRECTIVE
1595            }
1596            ErrorCode::TypeWithOnlyUnusedExternal => &TYPE_WITH_ONLY_UNUSED_EXTERNAL,
1597            ErrorCode::ProvidesOnNonObjectField => &PROVIDES_ON_NON_OBJECT_FIELD,
1598            ErrorCode::KeyInvalidFieldsType => &KEY_INVALID_FIELDS_TYPE,
1599            ErrorCode::ProvidesInvalidFieldsType => &PROVIDES_INVALID_FIELDS_TYPE,
1600            ErrorCode::RequiresInvalidFieldsType => &REQUIRES_INVALID_FIELDS_TYPE,
1601            ErrorCode::KeyInvalidFields => &KEY_INVALID_FIELDS,
1602            ErrorCode::ProvidesInvalidFields => &PROVIDES_INVALID_FIELDS,
1603            ErrorCode::RequiresInvalidFields => &REQUIRES_INVALID_FIELDS,
1604            ErrorCode::KeyFieldsSelectInvalidType => &KEY_FIELDS_SELECT_INVALID_TYPE,
1605            ErrorCode::RootQueryUsed => &ROOT_QUERY_USED,
1606            ErrorCode::RootMutationUsed => &ROOT_MUTATION_USED,
1607            ErrorCode::RootSubscriptionUsed => &ROOT_SUBSCRIPTION_USED,
1608            ErrorCode::InvalidSubgraphName => &INVALID_SUBGRAPH_NAME,
1609            ErrorCode::NoQueries => &NO_QUERIES,
1610            ErrorCode::InterfaceFieldNoImplem => &INTERFACE_FIELD_NO_IMPLEM,
1611            ErrorCode::TypeKindMismatch => &TYPE_KIND_MISMATCH,
1612            ErrorCode::ExternalTypeMismatch => &EXTERNAL_TYPE_MISMATCH,
1613            ErrorCode::ExternalArgumentMissing => &EXTERNAL_ARGUMENT_MISSING,
1614            ErrorCode::ExternalArgumentTypeMismatch => &EXTERNAL_ARGUMENT_TYPE_MISMATCH,
1615            ErrorCode::ExternalArgumentDefaultMismatch => &EXTERNAL_ARGUMENT_DEFAULT_MISMATCH,
1616            ErrorCode::ExternalOnInterface => &EXTERNAL_ON_INTERFACE,
1617            ErrorCode::MergedDirectiveApplicationOnExternal => {
1618                &MERGED_DIRECTIVE_APPLICATION_ON_EXTERNAL
1619            }
1620            ErrorCode::FieldTypeMismatch => &FIELD_TYPE_MISMATCH,
1621            ErrorCode::FieldArgumentTypeMismatch => &FIELD_ARGUMENT_TYPE_MISMATCH,
1622            ErrorCode::InputFieldDefaultMismatch => &INPUT_FIELD_DEFAULT_MISMATCH,
1623            ErrorCode::FieldArgumentDefaultMismatch => &FIELD_ARGUMENT_DEFAULT_MISMATCH,
1624            ErrorCode::ExtensionWithNoBase => &EXTENSION_WITH_NO_BASE,
1625            ErrorCode::ExternalMissingOnBase => &EXTERNAL_MISSING_ON_BASE,
1626            ErrorCode::InvalidFieldSharing => &INVALID_FIELD_SHARING,
1627            ErrorCode::InvalidShareableUsage => &INVALID_SHAREABLE_USAGE,
1628            ErrorCode::InvalidLinkDirectiveUsage => &INVALID_LINK_DIRECTIVE_USAGE,
1629            ErrorCode::InvalidLinkIdentifier => &INVALID_LINK_IDENTIFIER,
1630            ErrorCode::LinkImportNameMismatch => &LINK_IMPORT_NAME_MISMATCH,
1631            ErrorCode::ReferencedInaccessible => &REFERENCED_INACCESSIBLE,
1632            ErrorCode::DefaultValueUsesInaccessible => &DEFAULT_VALUE_USES_INACCESSIBLE,
1633            ErrorCode::QueryRootTypeInaccessible => &QUERY_ROOT_TYPE_INACCESSIBLE,
1634            ErrorCode::RequiredInaccessible => &REQUIRED_INACCESSIBLE,
1635            ErrorCode::ImplementedByInaccessible => &IMPLEMENTED_BY_INACCESSIBLE,
1636            ErrorCode::DisallowedInaccessible => &DISALLOWED_INACCESSIBLE,
1637            ErrorCode::OnlyInaccessibleChildren => &ONLY_INACCESSIBLE_CHILDREN,
1638            ErrorCode::RequiredInputFieldMissingInSomeSubgraph => {
1639                &REQUIRED_INPUT_FIELD_MISSING_IN_SOME_SUBGRAPH
1640            }
1641            ErrorCode::RequiredArgumentMissingInSomeSubgraph => {
1642                &REQUIRED_ARGUMENT_MISSING_IN_SOME_SUBGRAPH
1643            }
1644            ErrorCode::EmptyMergedInputType => &EMPTY_MERGED_INPUT_TYPE,
1645            ErrorCode::EnumValueMismatch => &ENUM_VALUE_MISMATCH,
1646            ErrorCode::EmptyMergedEnumType => &EMPTY_MERGED_ENUM_TYPE,
1647            ErrorCode::ShareableHasMismatchedRuntimeTypes => {
1648                &SHAREABLE_HAS_MISMATCHED_RUNTIME_TYPES
1649            }
1650            ErrorCode::SatisfiabilityError => &SATISFIABILITY_ERROR,
1651            ErrorCode::OverrideFromSelfError => &OVERRIDE_FROM_SELF_ERROR,
1652            ErrorCode::OverrideSourceHasOverride => &OVERRIDE_SOURCE_HAS_OVERRIDE,
1653            ErrorCode::OverrideCollisionWithAnotherDirective => {
1654                &OVERRIDE_COLLISION_WITH_ANOTHER_DIRECTIVE
1655            }
1656            ErrorCode::OverrideOnInterface => &OVERRIDE_ON_INTERFACE,
1657            ErrorCode::UnsupportedFeature => &UNSUPPORTED_FEATURE,
1658            ErrorCode::InvalidFederationSupergraph => &INVALID_FEDERATION_SUPERGRAPH,
1659            ErrorCode::DownstreamServiceError => &DOWNSTREAM_SERVICE_ERROR,
1660            ErrorCode::DirectiveCompositionError => &DIRECTIVE_COMPOSITION_ERROR,
1661            ErrorCode::InterfaceObjectUsageError => &INTERFACE_OBJECT_USAGE_ERROR,
1662            ErrorCode::InterfaceKeyNotOnImplementation => &INTERFACE_KEY_NOT_ON_IMPLEMENTATION,
1663            ErrorCode::InterfaceKeyMissingImplementationType => {
1664                &INTERFACE_KEY_MISSING_IMPLEMENTATION_TYPE
1665            }
1666            ErrorCode::UnsupportedFederationVersion => &UNSUPPORTED_FEDERATION_VERSION,
1667            ErrorCode::UnsupportedFederationDirective => &UNSUPPORTED_FEDERATION_DIRECTIVE,
1668            ErrorCode::QueryPlanComplexityExceededError => &QUERY_PLAN_COMPLEXITY_EXCEEDED,
1669        }
1670    }
1671}