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