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#[macro_export]
35macro_rules! internal_error {
36 ( $( $arg:tt )+ ) => {
37 $crate::error::FederationError::internal(format!( $( $arg )+ ))
38 }
39}
40
41#[macro_export]
57macro_rules! bail {
58 ( $( $arg:tt )+ ) => {
59 return Err($crate::internal_error!( $( $arg )+ ).into())
60 }
61}
62
63#[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#[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#[derive(Clone, Debug)]
125pub struct SubgraphLocation {
126 pub subgraph: String, 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, 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 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#[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)] InternalRebaseError(#[from] crate::operation::RebaseError),
534 #[error("{message}")]
536 InternalUnmergeableFields { message: String },
537 #[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 SingleFederationError::FromContextParseError { .. } => ErrorCode::InvalidGraphQL,
844 SingleFederationError::UnsupportedSpreadDirective { .. } => ErrorCode::InvalidGraphQL,
847 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 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#[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
1238impl 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
1284pub 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 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 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
1339const 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 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
1380static DEFAULT_METADATA: ErrorCodeMetadata = ErrorCodeMetadata {
1385 added_in: "2.0.0",
1386 replaces: &[],
1387};
1388
1389struct ErrorCodeCategory<TElement: Clone + Into<String>> {
1390 extract_code: Box<dyn 'static + Send + Sync + Fn(TElement) -> String>,
1392 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 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}