diff --git a/website/app/docs/[...slug]/page.tsx b/website/app/docs/[...slug]/page.tsx
index 9a6745f5d16..9b1ca15a349 100644
--- a/website/app/docs/[...slug]/page.tsx
+++ b/website/app/docs/[...slug]/page.tsx
@@ -72,7 +72,7 @@ export async function generateMetadata({
if (rel === null) {
return {};
}
- const { title, description, tags } = readFrontmatter(
+ const { title, metaTitle, description, tags } = readFrontmatter(
path.join(CONTENT_ROOT, rel),
);
const docTags = Array.isArray(tags)
@@ -82,10 +82,13 @@ export async function generateMetadata({
// Surface the product in the title tag ("OpenAPI Adapter - Hot Chocolate"),
// since searches almost always include the product name. Skip the suffix on
- // product index pages, where the title already is the product name.
+ // product index pages, where the title already is the product name. A page
+ // may set `metaTitle` to override the tag verbatim (no product suffix) while
+ // keeping a terse on-page heading.
const product = docBreadcrumbs(slug.slice(0, 1))[0]?.name;
const pageTitle =
- title && product && title !== product ? `${title} - ${product}` : title;
+ metaTitle ??
+ (title && product && title !== product ? `${title} - ${product}` : title);
const canonical = `/docs/${slug.join("/")}`;
diff --git a/website/content/docs/fusion/composition.md b/website/content/docs/fusion/composition.md
index 96b0b208a3b..6a00c8756c7 100644
--- a/website/content/docs/fusion/composition.md
+++ b/website/content/docs/fusion/composition.md
@@ -78,7 +78,7 @@ Performs reachability analysis. Starting from the root types, the pipeline walks
A few rules account for most composition failures. Knowing the shape of the error helps you spot the cause quickly.
-**Two source schemas return different types for the same field.** If `Product.price` is `Float` in one source schema and `Int` in another, composition fails with `OUTPUT_FIELD_TYPES_NOT_MERGEABLE`. Align the types in the source schemas.
+**Two source schemas return incompatible types for the same field.** If `Product.price` is `Float` in one source schema and `Int` in another, composition fails with `OUTPUT_FIELD_TYPES_NOT_MERGEABLE`. Scalar and enum return types must match exactly, while object, interface, and union types merge when one declared type is a supertype of the others (for example, `Product` and a `union FeaturedItem = Product` merge to `FeaturedItem`). Align the types when no common supertype exists.
**A field is defined in multiple source schemas without `@shareable`.** Defining `User.name` in both Accounts and Reviews without marking it `@shareable` produces `INVALID_FIELD_SHARING`.
@@ -116,74 +116,74 @@ The placeholders `{0}`, `{1}`, etc. in the message column are replaced with the
## Errors
-| Code | Message | How to resolve |
-| ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
-| `CONFLICTING_SOURCE_SCHEMA_NAME` | '\{0\}' conflicts with the existing source schema name '\{1\}'. Either rename '\{0\}' to '\{1\}' if they're the same, or rename '\{0\}' to something else if they're different. | Two source schemas were registered under names that the composition treats as the same identity. Rename one of them in your composition configuration so each source schema has a unique name. |
-| [DISALLOWED_INACCESSIBLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Disallowed-Inaccessible-Elements) | (Message varies by element kind: built-in scalar, introspection type, introspection field, introspection argument, or built-in directive argument.) | Built-in scalars, introspection types and their members, and built-in directive arguments cannot be marked `@inaccessible`. Remove the directive from the offending element in the named source schema. |
-| [EMPTY_MERGED_ENUM_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Empty-Merged-Enum-Type) | The merged enum type '\{0\}' is empty. | Every value of the enum was excluded by `@inaccessible` or tag filters, leaving nothing to merge. Either expose at least one enum value or remove the type entirely. |
-| [EMPTY_MERGED_INPUT_OBJECT_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Empty-Merged-Input-Object-Type) | The merged input object type '\{0\}' is empty. | All fields of the input type were excluded after merging. Expose at least one input field or remove the input type from your source schemas. |
-| [EMPTY_MERGED_INTERFACE_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Empty-Merged-Interface-Type) | The merged interface type '\{0\}' is empty. | All fields of the interface were filtered out by `@inaccessible` or tag exclusions. Expose at least one field on the interface, remove the filters that hide them, or drop the interface from the schema. |
-| [EMPTY_MERGED_OBJECT_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Empty-Merged-Object-Type) | The merged object type '\{0\}' is empty. | Every field on the object type was excluded. Expose at least one field, or remove the type if it is no longer needed. |
-| [EMPTY_MERGED_UNION_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Empty-Merged-Union-Type) | The merged union type '\{0\}' is empty. | All members of the union were excluded by `@inaccessible` or tag exclusions. Expose at least one member type, remove the filters that hide them, or remove the union. |
-| [ENUM_TYPE_DEFAULT_VALUE_INACCESSIBLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Enum-Type-Default-Value-Inaccessible) | The default value of '\{0\}' references the inaccessible enum value '\{1\}'. | A default points to an enum value that is hidden from the composed schema. Either change the default to a value that is accessible or remove `@inaccessible` from the referenced enum value. |
-| [ENUM_VALUES_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-Enum-Values-Mismatch) | The enum type '\{0\}' in schema '\{1\}' must define the value '\{2\}'. | An enum is defined in more than one source schema and one of them is missing a value the others declare. Add the missing value to the named source schema so all definitions agree. |
-| [EXTERNAL_ARGUMENT_DEFAULT_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Argument-Default-Mismatch) | The default value '\{0\}' of external argument '\{1\}' in schema '\{2\}' differs from the default value of '\{3\}' in schema '\{4\}'. | The same argument has different defaults in the external definition and the owning source schema. Align the default values across both source schemas. |
-| [EXTERNAL_ARGUMENT_MISSING](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Argument-Missing) | The external field '\{0\}' in schema '\{1\}' must define the argument '\{2\}'. | An `@external` field declaration is missing an argument that exists on the canonical definition. Add the argument to the external declaration with a matching type. |
-| [EXTERNAL_ARGUMENT_TYPE_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Argument-Type-Mismatch) | The argument '\{0\}' on external field '\{1\}' in schema '\{2\}' has a different type (\{3\}) than it does in schema '\{4\}' (\{5\}). | The argument types of an `@external` declaration and the owning source schema disagree. Change the argument type in one of the source schemas so the signatures match exactly, including nullability. |
-| [EXTERNAL_MISSING_ON_BASE](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Missing-on-Base) | The external field '\{0\}' in schema '\{1\}' is not defined (non-external) in any other schema. | A field marked `@external` has no non-external definition anywhere. Add the canonical definition in another source schema, or remove `@external` if this source schema is meant to own the field. See [Field Ownership](./field-ownership-and-sharing.md). |
-| [EXTERNAL_ON_INTERFACE](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-on-Interface) | The interface field '\{0\}' in schema '\{1\}' must not be marked as external. | `@external` is not valid on interface fields. Remove `@external` from the interface field; if you need to mark concrete implementations as external, place the directive on the implementing object types instead. |
-| [EXTERNAL_OVERRIDE_COLLISION](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Override-Collision) | The external field '\{0\}' in schema '\{1\}' must not be annotated with the @override directive. | A field cannot be both `@external` and `@override`. Decide which source schema owns the field and apply only the appropriate directive. |
-| [EXTERNAL_PROVIDES_COLLISION](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Provides-Collision) | The external field '\{0\}' in schema '\{1\}' must not be annotated with the @provides directive. | `@external` declares a field as not owned here, while `@provides` declares it as supplied here. Remove one of the directives so the ownership story is unambiguous. |
-| [EXTERNAL_REQUIRE_COLLISION](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Require-Collision) | The external field '\{0\}' in schema '\{1\}' must not have arguments that are annotated with the @require directive. | An `@external` field cannot consume `@require` arguments because it is not actually executed in this subgraph. Remove `@require` from the arguments, or move the field to a source schema where it is owned. |
-| [EXTERNAL_TYPE_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Type-Mismatch) | The external field '\{0\}' in schema '\{1\}' has a different type (\{2\}) than it does in schema '\{3\}' (\{4\}). | The return type of the `@external` declaration differs from the canonical definition. Align the field type and nullability in both source schemas. |
-| [EXTERNAL_UNUSED](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Unused) | The external field '\{0\}' in schema '\{1\}' is not referenced by a @provides directive in the schema. | An `@external` field is declared but no `@provides` in this schema references it. Remove the unused declaration, or add a `@provides` that references the field. See [Field Ownership](./field-ownership-and-sharing.md). |
-| `FEDERATION_DIRECTIVE_NOT_SUPPORTED` | The @\{0\} directive is not supported. | The schema uses an Apollo Federation directive that Fusion does not support. Remove the directive or replace it with the equivalent Fusion construct. |
-| `FEDERATION_V1_NOT_SUPPORTED` | Federation v1 is not supported. | Upgrade the source schema to Federation v2 (or to native Fusion directives) before running composition. |
-| [FIELD_ARGUMENT_TYPES_NOT_MERGEABLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Field-Argument-Types-Mergeable) | The argument '\{0\}' has a different type shape in schema '\{1\}' than it does in schema '\{2\}'. | The argument has a fundamentally different type (different named type or different list/non-null structure) across source schemas. Pick one canonical type and update the other source schema to match. |
-| [FIELD_WITH_MISSING_REQUIRED_ARGUMENT](https://graphql.github.io/composite-schemas-spec/draft/#sec-Field-With-Missing-Required-Arguments) | The argument '\{0\}' must be defined as required in schema '\{1\}'. Arguments marked with @require are treated as non-required. | The argument is required in some source schemas and optional or `@require`-driven in another. Mark the argument as required in the named source schema, or align all source schemas on the same nullability. |
-| [IMPLEMENTED_BY_INACCESSIBLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Implemented-by-Inaccessible) | The field '\{0\}' implementing interface field '\{1\}' is inaccessible in the composed schema. | An object type implements an interface field, but its implementation is hidden. Either expose the implementing field or hide the interface field as well. |
-| [INPUT_FIELD_DEFAULT_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-Input-Field-Default-Mismatch) | The default value '\{0\}' of input field '\{1\}' in schema '\{2\}' differs from the default value of '\{3\}' in schema '\{4\}'. | The same input field has different defaults in two source schemas. Align the default value across all definitions of the input type. |
-| [INPUT_FIELD_TYPES_NOT_MERGEABLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Input-Field-Types-mergeable) | The input field '\{0\}' has a different type shape in schema '\{1\}' than it does in schema '\{2\}'. | An input field has a different type structure (named type, list, or nullability) across source schemas. Decide on the canonical type and update the other source schema. |
-| [INPUT_WITH_MISSING_REQUIRED_FIELDS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Input-With-Missing-Required-Fields) | The input type '\{0\}' in schema '\{1\}' must define the required field '\{2\}'. | One source schema requires a field on an input type that another source schema omits. Add the field (with the same type) to the named source schema so the input shape is consistent. |
-| `INPUT_WITH_MISSING_ONEOF` | The input type '\{0\}' in schema '\{1\}' must be annotated with the '@oneOf' directive, since the same type has been annotated with it in schema '\{2\}'. | The same input type is `@oneOf` in one source schema but not in another. Add `@oneOf` to the input type in the named source schema (or remove it from the other) so all definitions agree. |
-| [INTERFACE_FIELD_NO_IMPLEMENTATION](https://graphql.github.io/composite-schemas-spec/draft/#sec-Interface-Field-No-Implementation) | The merged object type '\{0\}' must implement the field '\{1\}' on interface '\{2\}'. | After merging, an object type declares it implements the interface but does not provide every field the interface requires. Add the missing field to the object type, or stop implementing the interface. |
-| [INVALID_FIELD_SHARING](https://graphql.github.io/composite-schemas-spec/draft/#sec-Invalid-Field-Sharing) | The field '\{0\}' in schema '\{1\}' must be shareable. | The same non-key field is owned by more than one source schema without an explicit sharing contract. Add `@shareable` to the field (or to the enclosing type, which applies to all of its fields) in every source schema that defines it, or move ownership to a single source schema. See [Field Ownership](./field-ownership-and-sharing.md). |
-| [INVALID_GRAPHQL](https://graphql.github.io/composite-schemas-spec/draft/#sec-Invalid-GraphQL) | Invalid GraphQL in source schema. Exception message: \{0\}. | The source schema does not parse as valid GraphQL. Read the included parser exception, fix the SDL in the offending source schema, and re-export. See [Getting Started](./getting-started.md) for how to export a source schema. |
-| [INVALID_SHAREABLE_USAGE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Invalid-Shareable-Usage) | The field '\{0\}' in schema '\{1\}' must not be marked as shareable. | `@shareable` was applied where it is not allowed (for example, on a field that is already governed by another ownership directive). Remove `@shareable` from the field. See [Field Ownership](./field-ownership-and-sharing.md). |
-| [IS_INVALID_FIELDS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Is-Invalid-Fields) | The @is directive on argument '\{0\}' in schema '\{1\}' specifies an invalid field selection against the composed schema. | The field selection map in `@is(field: ...)` does not resolve against the entity's fields. Update it to reference fields that actually exist on the parent type. See [Entities and Lookups](./entities-and-lookups.md). |
-| [IS_INVALID_FIELD_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Is-Invalid-Field-Type) | The @is directive on argument '\{0\}' in schema '\{1\}' must specify a string value for the 'field' argument. | The `field` argument was given as a non-string literal. Pass it as a quoted string, for example `@is(field: "id")`. |
-| [IS_INVALID_SYNTAX](https://graphql.github.io/composite-schemas-spec/draft/#sec-Is-Invalid-Syntax) | The @is directive on argument '\{0\}' in schema '\{1\}' contains invalid syntax in the 'field' argument. | The string value for `field` is not a valid field selection map. Rewrite it as a syntactically valid field selection map. |
-| [IS_INVALID_USAGE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Is-Invalid-Usage) | The @is directive on argument '\{0\}' in schema '\{1\}' is invalid because the declaring field is not a lookup field. | `@is` is only valid on arguments of lookup fields. Move `@is` to a lookup, or annotate the declaring field with `@lookup`. See [Entities and Lookups](./entities-and-lookups.md). |
-| [KEY_DIRECTIVE_IN_FIELDS_ARGUMENT](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Directive-in-Fields-Argument) | A @key directive on type '\{0\}' in schema '\{1\}' references field '\{2\}', which must not include directive applications. | The `fields` selection of `@key` cannot apply directives to the selected fields. Remove the directive applications from the selection set. See [Entities and Lookups](./entities-and-lookups.md). |
-| [KEY_FIELDS_HAS_ARGUMENTS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Fields-Has-Arguments) | A @key directive on type '\{0\}' in schema '\{1\}' references field '\{2\}', which must not have arguments. | A field referenced by `@key` is being called with arguments, which is not allowed for key fields. Either select an argument-less field or expose a derived argument-less field for use as a key. |
-| [KEY_FIELDS_SELECT_INVALID_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Fields-Select-Invalid-Type) | A @key directive on type '\{0\}' in schema '\{1\}' references field '\{2\}', which must not be a list, interface, or union type. | Key fields must resolve to scalar, enum, or object types, not lists, interfaces, or unions. Pick a different field for the key, or model the key as a scalar identifier. |
-| [KEY_INVALID_FIELDS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Invalid-Fields) | A @key directive on type '\{0\}' in schema '\{1\}' specifies an invalid field selection against the composed schema. | The `fields` selection refers to fields that do not exist on the type. Add the missing fields to the type or correct the selection set. See [Entities and Lookups](./entities-and-lookups.md). |
-| [KEY_INVALID_FIELDS_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Invalid-Fields-Type) | A @key directive on type '\{0\}' in schema '\{1\}' must specify a string value for the 'fields' argument. | The `fields` argument was given as a non-string literal. Pass it as a quoted string, for example `@key(fields: "id")`. |
-| [KEY_INVALID_SYNTAX](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Invalid-Syntax) | A @key directive on type '\{0\}' in schema '\{1\}' contains invalid syntax in the 'fields' argument. | The string value for `fields` is not a valid GraphQL selection set. Rewrite it as a syntactically valid selection. |
-| [LOOKUP_RETURNS_LIST](https://graphql.github.io/composite-schemas-spec/draft/#sec-Lookup-Returns-List) | The lookup field '\{0\}' in schema '\{1\}' must not return a list. | A `@lookup` field returned a list, which prevents the gateway from mapping a key to a single entity. Change the return type to a single nullable entity. See [Entities and Lookups](./entities-and-lookups.md). |
-| [NON_NULL_INPUT_FIELD_IS_INACCESSIBLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Non-Null-Input-Fields-cannot-be-inaccessible) | The non-null input field '\{0\}' in schema '\{1\}' must be accessible in the composed schema. | A required input field was hidden by `@inaccessible`, which would make the input impossible to construct from the gateway. Either make the field nullable or expose it. |
-| [NO_QUERIES](https://graphql.github.io/composite-schemas-spec/draft/#sec-No-Queries) | The merged query type has no accessible fields. | After merging and applying accessibility filters, no query fields remain. Expose at least one query field, or remove `@inaccessible` from the queries you intend to publish. |
-| [OUTPUT_FIELD_TYPES_NOT_MERGEABLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Output-Field-Types-Mergeable) | The output field '\{0\}' has a different type shape in schema '\{1\}' than it does in schema '\{2\}'. | Two source schemas return different types (different named type, different list shape, or different nullability) for the same field. Align the return types in both source schemas. |
-| [OVERRIDE_FROM_SELF](https://graphql.github.io/composite-schemas-spec/draft/#sec-Override-from-Self) | The @override directive on field '\{0\}' in schema '\{1\}' must not reference the same schema. | `@override(from: "...")` cannot point at the source schema that owns the directive. Set `from` to the name of the source schema the field is being taken from. See [Field Ownership](./field-ownership-and-sharing.md). |
-| [OVERRIDE_ON_INTERFACE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Override-on-Interface) | The interface field '\{0\}' in schema '\{1\}' must not be annotated with the @override directive. | `@override` cannot be applied to interface fields. Move the directive to the implementing object types if you need to take ownership of a specific implementation. See [Field Ownership](./field-ownership-and-sharing.md). |
-| [PROVIDES_DIRECTIVE_IN_FIELDS_ARGUMENT](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Directive-in-Fields-Argument) | The @provides directive on field '\{0\}' in schema '\{1\}' references field '\{2\}', which must not include directive applications. | The selection in `@provides(fields: ...)` cannot apply directives. Remove the directive applications from the selection. See [Field Ownership](./field-ownership-and-sharing.md). |
-| [PROVIDES_FIELDS_HAS_ARGUMENTS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Fields-Has-Arguments) | The @provides directive on field '\{0\}' in schema '\{1\}' references field '\{2\}', which must not have arguments. | A field selected by `@provides` is being called with arguments, which is not allowed. Pick an argument-less field or restructure the schema so the provided field needs no arguments. |
-| [PROVIDES_FIELDS_MISSING_EXTERNAL](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Fields-Missing-External) | The @provides directive on field '\{0\}' in schema '\{1\}' references field '\{2\}', which must be marked as external. | `@provides` only makes sense when the referenced field is `@external` here. Add `@external` to the referenced field in the same source schema. See [Field Ownership](./field-ownership-and-sharing.md). |
-| [PROVIDES_INVALID_FIELDS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Invalid-Fields) | The @provides directive on field '\{0\}' in schema '\{1\}' specifies an invalid field selection. | The selection points to fields that do not exist on the returned type. Update the selection so it matches fields that the returned type actually defines. |
-| [PROVIDES_INVALID_FIELDS_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Invalid-Fields-Type) | The @provides directive on field '\{0\}' in schema '\{1\}' must specify a string value for the 'fields' argument. | The `fields` argument was given as a non-string literal. Pass it as a quoted string. |
-| [PROVIDES_INVALID_SYNTAX](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Invalid-Syntax) | The @provides directive on field '\{0\}' in schema '\{1\}' contains invalid syntax in the 'fields' argument. | The selection set syntax in `fields` is invalid. Rewrite it as a valid GraphQL selection set. |
-| [PROVIDES_ON_NON_COMPOSITE_FIELD](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-on-Non-Composite-Field) | The field '\{0\}' in schema '\{1\}' includes a @provides directive, but does not return a composite type. | `@provides` only applies when a field returns an object, interface, or union, because the directive describes which sub-fields are also delivered. Remove `@provides`, or change the field to return a composite type. |
-| [QUERY_ROOT_TYPE_INACCESSIBLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Query-Root-Type-Inaccessible) | The root query type in schema '\{0\}' must be accessible. | The query root cannot be marked `@inaccessible`. Remove the directive from the root query type. |
-| [REFERENCE_TO_INACCESSIBLE_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Reference-To-Inaccessible-Type) | (Message varies by reference site: field argument, input field, or output field.) | A publicly accessible position (a field argument, input field, or output field) references a type that has been hidden from the composed schema. Either expose the referenced type or change the position to use a publicly accessible type. |
-| [REFERENCE_TO_INTERNAL_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Reference-To-Internal-Type) | The merged field '\{0\}' in type '\{1\}' cannot reference the internal type '\{2\}'. | A public field returns an internal type, which would leak the internal type into the composed schema. Either mark the field as internal as well, or change the return type to a non-internal one. |
-| [REQUIRE_INVALID_FIELDS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Require-Invalid-Fields) | The @require directive on argument '\{0\}' in schema '\{1\}' specifies an invalid field selection against the composed schema. | The field selection map in `@require(field: ...)` references fields that the parent type does not expose. Update it to reference fields that exist on the parent. See [Entities and Lookups](./entities-and-lookups.md). |
-| [REQUIRE_INVALID_FIELD_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Require-Invalid-Field-Type) | The @require directive on argument '\{0\}' in schema '\{1\}' must specify a string value for the 'field' argument. | The `field` argument must be a string literal. Pass it as a quoted string. |
-| [REQUIRE_INVALID_SYNTAX](https://graphql.github.io/composite-schemas-spec/draft/#sec-Require-Invalid-Syntax) | The @require directive on argument '\{0\}' in schema '\{1\}' contains invalid syntax in the 'field' argument. | The `field` value is not a valid field selection map. Rewrite it as a syntactically valid field selection map. |
-| [ROOT_MUTATION_USED](https://graphql.github.io/composite-schemas-spec/draft/#sec-Root-Mutation-Used) | The root mutation type in schema '\{0\}' must be named 'Mutation'. | Fusion requires the root mutation type to use the canonical name `Mutation`. Rename the type in the named source schema. A type named `Mutation` must not exist unless it is the root mutation type. |
-| [ROOT_QUERY_USED](https://graphql.github.io/composite-schemas-spec/draft/#sec-Root-Query-Used) | The root query type in schema '\{0\}' must be named 'Query'. | Fusion requires the root query type to use the canonical name `Query`. Rename the type in the named source schema. A type named `Query` must not exist unless it is the root query type. See [Getting Started](./getting-started.md) for the expected schema layout. |
-| [ROOT_SUBSCRIPTION_USED](https://graphql.github.io/composite-schemas-spec/draft/#sec-Root-Subscription-Used) | The root subscription type in schema '\{0\}' must be named 'Subscription'. | Fusion requires the root subscription type to use the canonical name `Subscription`. Rename the type in the named source schema. A type named `Subscription` must not exist unless it is the root subscription type. |
-| [TYPE_KIND_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-Type-Kind-Mismatch) | The type '\{0\}' has a different kind in schema '\{1\}' (\{2\}) than it does in schema '\{3\}' (\{4\}). | The same type name was used for different kinds (for example, an object in one source schema and an interface in another). Decide which kind is correct and update the other source schema, or rename one of the types so they no longer collide. |
-| [UNSATISFIABLE_QUERY_PATH](https://graphql.github.io/composite-schemas-spec/draft/#sec-Unsatisfiable-Query-Path) | (Message varies. Includes the unreachable field, the path the validator tried, and the lookups it considered.) | Some reachable field cannot be resolved through the available `@lookup` and `@key` paths. See [Diagnosing UNSATISFIABLE_QUERY_PATH Errors](#diagnosing-unsatisfiable_query_path-errors) for how to read the message and fix the underlying gap. |
+| Code | Message | How to resolve |
+| ------------------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `CONFLICTING_SOURCE_SCHEMA_NAME` | '\{0\}' conflicts with the existing source schema name '\{1\}'. Either rename '\{0\}' to '\{1\}' if they're the same, or rename '\{0\}' to something else if they're different. | Two source schemas were registered under names that the composition treats as the same identity. Rename one of them in your composition configuration so each source schema has a unique name. |
+| [DISALLOWED_INACCESSIBLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Disallowed-Inaccessible-Elements) | (Message varies by element kind: built-in scalar, introspection type, introspection field, introspection argument, or built-in directive argument.) | Built-in scalars, introspection types and their members, and built-in directive arguments cannot be marked `@inaccessible`. Remove the directive from the offending element in the named source schema. |
+| [EMPTY_MERGED_ENUM_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Empty-Merged-Enum-Type) | The merged enum type '\{0\}' is empty. | Every value of the enum was excluded by `@inaccessible` or tag filters, leaving nothing to merge. Either expose at least one enum value or remove the type entirely. |
+| [EMPTY_MERGED_INPUT_OBJECT_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Empty-Merged-Input-Object-Type) | The merged input object type '\{0\}' is empty. | All fields of the input type were excluded after merging. Expose at least one input field or remove the input type from your source schemas. |
+| [EMPTY_MERGED_INTERFACE_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Empty-Merged-Interface-Type) | The merged interface type '\{0\}' is empty. | All fields of the interface were filtered out by `@inaccessible` or tag exclusions. Expose at least one field on the interface, remove the filters that hide them, or drop the interface from the schema. |
+| [EMPTY_MERGED_OBJECT_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Empty-Merged-Object-Type) | The merged object type '\{0\}' is empty. | Every field on the object type was excluded. Expose at least one field, or remove the type if it is no longer needed. |
+| [EMPTY_MERGED_UNION_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Empty-Merged-Union-Type) | The merged union type '\{0\}' is empty. | All members of the union were excluded by `@inaccessible` or tag exclusions. Expose at least one member type, remove the filters that hide them, or remove the union. |
+| [ENUM_TYPE_DEFAULT_VALUE_INACCESSIBLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Enum-Type-Default-Value-Inaccessible) | The default value of '\{0\}' references the inaccessible enum value '\{1\}'. | A default points to an enum value that is hidden from the composed schema. Either change the default to a value that is accessible or remove `@inaccessible` from the referenced enum value. |
+| [ENUM_VALUES_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-Enum-Values-Mismatch) | The enum type '\{0\}' in schema '\{1\}' must define the value '\{2\}'. | An enum is defined in more than one source schema and one of them is missing a value the others declare. Add the missing value to the named source schema so all definitions agree. |
+| [EXTERNAL_ARGUMENT_DEFAULT_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Argument-Default-Mismatch) | The default value '\{0\}' of external argument '\{1\}' in schema '\{2\}' differs from the default value of '\{3\}' in schema '\{4\}'. | The same argument has different defaults in the external definition and the owning source schema. Align the default values across both source schemas. |
+| [EXTERNAL_ARGUMENT_MISSING](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Argument-Missing) | The external field '\{0\}' in schema '\{1\}' must define the argument '\{2\}'. | An `@external` field declaration is missing an argument that exists on the canonical definition. Add the argument to the external declaration with a matching type. |
+| [EXTERNAL_ARGUMENT_TYPE_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Argument-Type-Mismatch) | The argument '\{0\}' on external field '\{1\}' in schema '\{2\}' has a different type (\{3\}) than it does in schema '\{4\}' (\{5\}). | The argument types of an `@external` declaration and the owning source schema disagree. Change the argument type in one of the source schemas so the signatures match exactly, including nullability. |
+| [EXTERNAL_MISSING_ON_BASE](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Missing-on-Base) | The external field '\{0\}' in schema '\{1\}' is not defined (non-external) in any other schema. | A field marked `@external` has no non-external definition anywhere. Add the canonical definition in another source schema, or remove `@external` if this source schema is meant to own the field. See [Field Ownership](./field-ownership-and-sharing.md). |
+| [EXTERNAL_ON_INTERFACE](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-on-Interface) | The interface field '\{0\}' in schema '\{1\}' must not be marked as external. | `@external` is not valid on interface fields. Remove `@external` from the interface field; if you need to mark concrete implementations as external, place the directive on the implementing object types instead. |
+| [EXTERNAL_OVERRIDE_COLLISION](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Override-Collision) | The external field '\{0\}' in schema '\{1\}' must not be annotated with the @override directive. | A field cannot be both `@external` and `@override`. Decide which source schema owns the field and apply only the appropriate directive. |
+| [EXTERNAL_PROVIDES_COLLISION](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Provides-Collision) | The external field '\{0\}' in schema '\{1\}' must not be annotated with the @provides directive. | `@external` declares a field as not owned here, while `@provides` declares it as supplied here. Remove one of the directives so the ownership story is unambiguous. |
+| [EXTERNAL_REQUIRE_COLLISION](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Require-Collision) | The external field '\{0\}' in schema '\{1\}' must not have arguments that are annotated with the @require directive. | An `@external` field cannot consume `@require` arguments because it is not actually executed in this subgraph. Remove `@require` from the arguments, or move the field to a source schema where it is owned. |
+| [EXTERNAL_TYPE_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Type-Mismatch) | The external field '\{0\}' in schema '\{1\}' has a different type (\{2\}) than it does in schema '\{3\}' (\{4\}). | The return type of the `@external` declaration differs from the canonical definition. Align the field type and nullability in both source schemas. |
+| [EXTERNAL_UNUSED](https://graphql.github.io/composite-schemas-spec/draft/#sec-External-Unused) | The external field '\{0\}' in schema '\{1\}' is not referenced by a @provides directive in the schema. | An `@external` field is declared but no `@provides` in this schema references it. Remove the unused declaration, or add a `@provides` that references the field. See [Field Ownership](./field-ownership-and-sharing.md). |
+| `FEDERATION_DIRECTIVE_NOT_SUPPORTED` | The @\{0\} directive is not supported. | The schema uses an Apollo Federation directive that Fusion does not support. Remove the directive or replace it with the equivalent Fusion construct. |
+| `FEDERATION_V1_NOT_SUPPORTED` | Federation v1 is not supported. | Upgrade the source schema to Federation v2 (or to native Fusion directives) before running composition. |
+| [FIELD_ARGUMENT_TYPES_NOT_MERGEABLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Field-Argument-Types-Mergeable) | The argument '\{0\}' has a different type shape in schema '\{1\}' than it does in schema '\{2\}'. | The argument has a fundamentally different type (different named type or different list/non-null structure) across source schemas. Pick one canonical type and update the other source schema to match. |
+| [FIELD_WITH_MISSING_REQUIRED_ARGUMENT](https://graphql.github.io/composite-schemas-spec/draft/#sec-Field-With-Missing-Required-Arguments) | The argument '\{0\}' must be defined as required in schema '\{1\}'. Arguments marked with @require are treated as non-required. | The argument is required in some source schemas and optional or `@require`-driven in another. Mark the argument as required in the named source schema, or align all source schemas on the same nullability. |
+| [IMPLEMENTED_BY_INACCESSIBLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Implemented-by-Inaccessible) | The field '\{0\}' implementing interface field '\{1\}' is inaccessible in the composed schema. | An object type implements an interface field, but its implementation is hidden. Either expose the implementing field or hide the interface field as well. |
+| [INPUT_FIELD_DEFAULT_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-Input-Field-Default-Mismatch) | The default value '\{0\}' of input field '\{1\}' in schema '\{2\}' differs from the default value of '\{3\}' in schema '\{4\}'. | The same input field has different defaults in two source schemas. Align the default value across all definitions of the input type. |
+| [INPUT_FIELD_TYPES_NOT_MERGEABLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Input-Field-Types-mergeable) | The input field '\{0\}' has a different type shape in schema '\{1\}' than it does in schema '\{2\}'. | An input field has a different type structure (named type, list, or nullability) across source schemas. Decide on the canonical type and update the other source schema. |
+| [INPUT_WITH_MISSING_REQUIRED_FIELDS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Input-With-Missing-Required-Fields) | The input type '\{0\}' in schema '\{1\}' must define the required field '\{2\}'. | One source schema requires a field on an input type that another source schema omits. Add the field (with the same type) to the named source schema so the input shape is consistent. |
+| `INPUT_WITH_MISSING_ONEOF` | The input type '\{0\}' in schema '\{1\}' must be annotated with the '@oneOf' directive, since the same type has been annotated with it in schema '\{2\}'. | The same input type is `@oneOf` in one source schema but not in another. Add `@oneOf` to the input type in the named source schema (or remove it from the other) so all definitions agree. |
+| [INTERFACE_FIELD_NO_IMPLEMENTATION](https://graphql.github.io/composite-schemas-spec/draft/#sec-Interface-Field-No-Implementation) | The merged object type '\{0\}' must implement the field '\{1\}' on interface '\{2\}'. | After merging, an object type declares it implements the interface but does not provide every field the interface requires. Add the missing field to the object type, or stop implementing the interface. |
+| [INVALID_FIELD_SHARING](https://graphql.github.io/composite-schemas-spec/draft/#sec-Invalid-Field-Sharing) | The field '\{0\}' in schema '\{1\}' must be shareable. | The same non-key field is owned by more than one source schema without an explicit sharing contract. Add `@shareable` to the field (or to the enclosing type, which applies to all of its fields) in every source schema that defines it, or move ownership to a single source schema. See [Field Ownership](./field-ownership-and-sharing.md). |
+| [INVALID_GRAPHQL](https://graphql.github.io/composite-schemas-spec/draft/#sec-Invalid-GraphQL) | Invalid GraphQL in source schema. Exception message: \{0\}. | The source schema does not parse as valid GraphQL. Read the included parser exception, fix the SDL in the offending source schema, and re-export. See [Getting Started](./getting-started.md) for how to export a source schema. |
+| [INVALID_SHAREABLE_USAGE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Invalid-Shareable-Usage) | The field '\{0\}' in schema '\{1\}' must not be marked as shareable. | `@shareable` was applied where it is not allowed (for example, on a field that is already governed by another ownership directive). Remove `@shareable` from the field. See [Field Ownership](./field-ownership-and-sharing.md). |
+| [IS_INVALID_FIELDS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Is-Invalid-Fields) | The @is directive on argument '\{0\}' in schema '\{1\}' specifies an invalid field selection against the composed schema. | The field selection map in `@is(field: ...)` does not resolve against the entity's fields. Update it to reference fields that actually exist on the parent type. See [Entities and Lookups](./entities-and-lookups.md). |
+| [IS_INVALID_FIELD_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Is-Invalid-Field-Type) | The @is directive on argument '\{0\}' in schema '\{1\}' must specify a string value for the 'field' argument. | The `field` argument was given as a non-string literal. Pass it as a quoted string, for example `@is(field: "id")`. |
+| [IS_INVALID_SYNTAX](https://graphql.github.io/composite-schemas-spec/draft/#sec-Is-Invalid-Syntax) | The @is directive on argument '\{0\}' in schema '\{1\}' contains invalid syntax in the 'field' argument. | The string value for `field` is not a valid field selection map. Rewrite it as a syntactically valid field selection map. |
+| [IS_INVALID_USAGE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Is-Invalid-Usage) | The @is directive on argument '\{0\}' in schema '\{1\}' is invalid because the declaring field is not a lookup field. | `@is` is only valid on arguments of lookup fields. Move `@is` to a lookup, or annotate the declaring field with `@lookup`. See [Entities and Lookups](./entities-and-lookups.md). |
+| [KEY_DIRECTIVE_IN_FIELDS_ARGUMENT](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Directive-in-Fields-Argument) | A @key directive on type '\{0\}' in schema '\{1\}' references field '\{2\}', which must not include directive applications. | The `fields` selection of `@key` cannot apply directives to the selected fields. Remove the directive applications from the selection set. See [Entities and Lookups](./entities-and-lookups.md). |
+| [KEY_FIELDS_SELECT_INVALID_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Fields-Select-Invalid-Type) | A @key directive on type '\{0\}' in schema '\{1\}' references field '\{2\}', which must not be a list, interface, or union type. | Key fields must resolve to scalar, enum, or object types, not lists, interfaces, or unions. Pick a different field for the key, or model the key as a scalar identifier. |
+| [KEY_INVALID_ARGUMENTS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Invalid-Arguments) | A @key directive on type '\{0\}' in schema '\{1\}' specifies invalid arguments. \{2\} | Key fields support constant arguments. Remove or correct any argument that is unknown, has an incompatible value type, or leaves a required argument unsupplied. |
+| [KEY_INVALID_FIELDS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Invalid-Fields) | A @key directive on type '\{0\}' in schema '\{1\}' specifies an invalid field selection against the composed schema. | The `fields` selection refers to fields that do not exist on the type. Add the missing fields to the type or correct the selection set. See [Entities and Lookups](./entities-and-lookups.md). |
+| [KEY_INVALID_FIELDS_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Invalid-Fields-Type) | A @key directive on type '\{0\}' in schema '\{1\}' must specify a string value for the 'fields' argument. | The `fields` argument was given as a non-string literal. Pass it as a quoted string, for example `@key(fields: "id")`. |
+| [KEY_INVALID_SYNTAX](https://graphql.github.io/composite-schemas-spec/draft/#sec-Key-Invalid-Syntax) | A @key directive on type '\{0\}' in schema '\{1\}' contains invalid syntax in the 'fields' argument. | The string value for `fields` is not a valid GraphQL selection set. Rewrite it as a syntactically valid selection. |
+| [LOOKUP_RETURNS_LIST](https://graphql.github.io/composite-schemas-spec/draft/#sec-Lookup-Returns-List) | The lookup field '\{0\}' in schema '\{1\}' must not return a list. | A `@lookup` field returned a list, which prevents the gateway from mapping a key to a single entity. Change the return type to a single nullable entity. See [Entities and Lookups](./entities-and-lookups.md). |
+| [NON_NULL_INPUT_FIELD_IS_INACCESSIBLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Non-Null-Input-Fields-cannot-be-inaccessible) | The non-null input field '\{0\}' in schema '\{1\}' must be accessible in the composed schema. | A required input field was hidden by `@inaccessible`, which would make the input impossible to construct from the gateway. Either make the field nullable or expose it. |
+| [NO_QUERIES](https://graphql.github.io/composite-schemas-spec/draft/#sec-No-Queries) | The merged query type has no accessible fields. | After merging and applying accessibility filters, no query fields remain. Expose at least one query field, or remove `@inaccessible` from the queries you intend to publish. |
+| [OUTPUT_FIELD_TYPES_NOT_MERGEABLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Output-Field-Types-Mergeable) | The output field '\{0\}' has a different type shape in schema '\{1\}' than it does in schema '\{2\}'. | The field's return type cannot be unified across source schemas: leaf types (scalar or enum) differ in name or kind, the list shape differs, or composite types (object, interface, or union) share no common supertype. Nullability differences and composite types with a common supertype merge automatically; otherwise align the return types. |
+| [OVERRIDE_FROM_SELF](https://graphql.github.io/composite-schemas-spec/draft/#sec-Override-from-Self) | The @override directive on field '\{0\}' in schema '\{1\}' must not reference the same schema. | `@override(from: "...")` cannot point at the source schema that owns the directive. Set `from` to the name of the source schema the field is being taken from. See [Field Ownership](./field-ownership-and-sharing.md). |
+| [OVERRIDE_ON_INTERFACE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Override-on-Interface) | The interface field '\{0\}' in schema '\{1\}' must not be annotated with the @override directive. | `@override` cannot be applied to interface fields. Move the directive to the implementing object types if you need to take ownership of a specific implementation. See [Field Ownership](./field-ownership-and-sharing.md). |
+| [PROVIDES_DIRECTIVE_IN_FIELDS_ARGUMENT](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Directive-in-Fields-Argument) | The @provides directive on field '\{0\}' in schema '\{1\}' references field '\{2\}', which must not include directive applications. | The selection in `@provides(fields: ...)` cannot apply directives. Remove the directive applications from the selection. See [Field Ownership](./field-ownership-and-sharing.md). |
+| [PROVIDES_FIELDS_HAS_ARGUMENTS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Fields-Has-Arguments) | The @provides directive on field '\{0\}' in schema '\{1\}' references field '\{2\}', which must not have arguments. | A field selected by `@provides` is being called with arguments, which is not allowed. Pick an argument-less field or restructure the schema so the provided field needs no arguments. |
+| [PROVIDES_FIELDS_MISSING_EXTERNAL](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Fields-Missing-External) | The @provides directive on field '\{0\}' in schema '\{1\}' references field '\{2\}', which must be marked as external. | `@provides` only makes sense when the referenced field is `@external` here. Add `@external` to the referenced field in the same source schema. See [Field Ownership](./field-ownership-and-sharing.md). |
+| [PROVIDES_INVALID_FIELDS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Invalid-Fields) | The @provides directive on field '\{0\}' in schema '\{1\}' specifies an invalid field selection. | The selection points to fields that do not exist on the returned type. Update the selection so it matches fields that the returned type actually defines. |
+| [PROVIDES_INVALID_FIELDS_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Invalid-Fields-Type) | The @provides directive on field '\{0\}' in schema '\{1\}' must specify a string value for the 'fields' argument. | The `fields` argument was given as a non-string literal. Pass it as a quoted string. |
+| [PROVIDES_INVALID_SYNTAX](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-Invalid-Syntax) | The @provides directive on field '\{0\}' in schema '\{1\}' contains invalid syntax in the 'fields' argument. | The selection set syntax in `fields` is invalid. Rewrite it as a valid GraphQL selection set. |
+| [PROVIDES_ON_NON_COMPOSITE_FIELD](https://graphql.github.io/composite-schemas-spec/draft/#sec-Provides-on-Non-Composite-Field) | The field '\{0\}' in schema '\{1\}' includes a @provides directive, but does not return a composite type. | `@provides` only applies when a field returns an object, interface, or union, because the directive describes which sub-fields are also delivered. Remove `@provides`, or change the field to return a composite type. |
+| [QUERY_ROOT_TYPE_INACCESSIBLE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Query-Root-Type-Inaccessible) | The root query type in schema '\{0\}' must be accessible. | The query root cannot be marked `@inaccessible`. Remove the directive from the root query type. |
+| [REFERENCE_TO_INACCESSIBLE_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Reference-To-Inaccessible-Type) | (Message varies by reference site: field argument, input field, or output field.) | A publicly accessible position (a field argument, input field, or output field) references a type that has been hidden from the composed schema. Either expose the referenced type or change the position to use a publicly accessible type. |
+| [REFERENCE_TO_INTERNAL_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Reference-To-Internal-Type) | The merged field '\{0\}' in type '\{1\}' cannot reference the internal type '\{2\}'. | A public field returns an internal type, which would leak the internal type into the composed schema. Either mark the field as internal as well, or change the return type to a non-internal one. |
+| [REQUIRE_INVALID_FIELDS](https://graphql.github.io/composite-schemas-spec/draft/#sec-Require-Invalid-Fields) | The @require directive on argument '\{0\}' in schema '\{1\}' specifies an invalid field selection against the composed schema. | The field selection map in `@require(field: ...)` references fields that the parent type does not expose. Update it to reference fields that exist on the parent. See [Entities and Lookups](./entities-and-lookups.md). |
+| [REQUIRE_INVALID_FIELD_TYPE](https://graphql.github.io/composite-schemas-spec/draft/#sec-Require-Invalid-Field-Type) | The @require directive on argument '\{0\}' in schema '\{1\}' must specify a string value for the 'field' argument. | The `field` argument must be a string literal. Pass it as a quoted string. |
+| [REQUIRE_INVALID_SYNTAX](https://graphql.github.io/composite-schemas-spec/draft/#sec-Require-Invalid-Syntax) | The @require directive on argument '\{0\}' in schema '\{1\}' contains invalid syntax in the 'field' argument. | The `field` value is not a valid field selection map. Rewrite it as a syntactically valid field selection map. |
+| [ROOT_MUTATION_USED](https://graphql.github.io/composite-schemas-spec/draft/#sec-Root-Mutation-Used) | The root mutation type in schema '\{0\}' must be named 'Mutation'. | Fusion requires the root mutation type to use the canonical name `Mutation`. Rename the type in the named source schema. A type named `Mutation` must not exist unless it is the root mutation type. |
+| [ROOT_QUERY_USED](https://graphql.github.io/composite-schemas-spec/draft/#sec-Root-Query-Used) | The root query type in schema '\{0\}' must be named 'Query'. | Fusion requires the root query type to use the canonical name `Query`. Rename the type in the named source schema. A type named `Query` must not exist unless it is the root query type. See [Getting Started](./getting-started.md) for the expected schema layout. |
+| [ROOT_SUBSCRIPTION_USED](https://graphql.github.io/composite-schemas-spec/draft/#sec-Root-Subscription-Used) | The root subscription type in schema '\{0\}' must be named 'Subscription'. | Fusion requires the root subscription type to use the canonical name `Subscription`. Rename the type in the named source schema. A type named `Subscription` must not exist unless it is the root subscription type. |
+| [TYPE_KIND_MISMATCH](https://graphql.github.io/composite-schemas-spec/draft/#sec-Type-Kind-Mismatch) | The type '\{0\}' has a different kind in schema '\{1\}' (\{2\}) than it does in schema '\{3\}' (\{4\}). | The same type name was used for different kinds (for example, an object in one source schema and an interface in another). Decide which kind is correct and update the other source schema, or rename one of the types so they no longer collide. |
+| [UNSATISFIABLE_QUERY_PATH](https://graphql.github.io/composite-schemas-spec/draft/#sec-Unsatisfiable-Query-Path) | (Message varies. Includes the unreachable field, the path the validator tried, and the lookups it considered.) | Some reachable field cannot be resolved through the available `@lookup` and `@key` paths. See [Diagnosing UNSATISFIABLE_QUERY_PATH Errors](#diagnosing-unsatisfiable_query_path-errors) for how to read the message and fix the underlying gap. |
## Warnings
diff --git a/website/content/docs/fusion/data-requirements-and-mapping.md b/website/content/docs/fusion/data-requirements-and-mapping.md
index 6b075d570fa..27dcf52a3dd 100644
--- a/website/content/docs/fusion/data-requirements-and-mapping.md
+++ b/website/content/docs/fusion/data-requirements-and-mapping.md
@@ -218,6 +218,24 @@ type Product {
The gateway traverses `seller.address.countryCode` on the entity and passes the resolved value as the `countryCode` argument.
+## Constant Arguments in Field Selections
+
+Fields referenced in a `@require` or `@is` field selection map may carry constant arguments to parameterize or disambiguate the selected field. This is useful when a field offers multiple representations via an argument, and the resolver always needs one specific form.
+
+**GraphQL schema**
+
+```graphql
+# Shipping subgraph
+type Product {
+ shippingCost(size: Int! @require(field: "dimension(unit: METRIC)")): Float
+ dimension(unit: Unit!): Int
+}
+```
+
+Here the `@require` path selects `dimension` with the constant argument `unit: METRIC`. The gateway evaluates this selection against the Products subgraph and passes the resulting value to `shippingCost`.
+
+Argument values in a field selection map must be constant literals (no variables). They must match the field's declared argument definitions, and all required arguments must be supplied. Violations surface as `IS_INVALID_FIELDS` for `@is` and `REQUIRE_INVALID_FIELDS` for `@require`. Note that `@provides` field selections must not include arguments at all; any argument usage there is reported as `PROVIDES_FIELDS_HAS_ARGUMENTS`.
+
## List Aggregation Paths
When an entity field is a list, you can use bracket notation to select a field from each element. The gateway collects the selected values into a flat list.
diff --git a/website/content/docs/fusion/directives-reference.md b/website/content/docs/fusion/directives-reference.md
index 4cc6923278e..b42138a0782 100644
--- a/website/content/docs/fusion/directives-reference.md
+++ b/website/content/docs/fusion/directives-reference.md
@@ -42,6 +42,8 @@ directive @key(fields: FieldSelectionSet!) repeatable on OBJECT | INTERFACE
Each `@key` directive on a type specifies one distinct unique key for that entity. Apply multiple `@key` directives to define alternative keys that the gateway can use to resolve the entity. Fields referenced in a key are implicitly shareable across subgraphs -- you do not need to add `@shareable` to key fields.
+Key fields may supply constant arguments to select a specific variant of a field (for example, `@key(fields: "id(scope: LOCAL)")`). Argument values must be constant literals (no variables), must match the field's declared argument definitions, and all required arguments must be supplied. Composition reports unknown, incompatible, or missing-required arguments as `KEY_INVALID_ARGUMENTS`.
+
**Example -- single key:**
```graphql
@@ -142,7 +144,7 @@ directive @is(field: FieldSelectionMap!) on ARGUMENT_DEFINITION
| -------- | -------------------- | ----------------------------------------------------------------------------- |
| `field` | `FieldSelectionMap!` | A selection map that describes the mapping from entity fields to the argument |
-When a lookup argument name matches the corresponding field on the return type, you can omit `@is`. Use `@is` when the names differ or when the mapping involves nested fields.
+When a lookup argument name matches the corresponding field on the return type, you can omit `@is`. Use `@is` when the names differ or when the mapping involves nested fields. Fields in the selection map may carry constant arguments (for example, `@is(field: "id(scope: LOCAL)")`); argument values must be constant literals (no variables), must match the field's argument definitions, and all required arguments must be supplied. Argument errors surface as `IS_INVALID_FIELDS`.
**Example -- argument name differs from field name:**
@@ -197,7 +199,7 @@ directive @require(field: FieldSelectionMap!) on ARGUMENT_DEFINITION
| -------- | -------------------- | ----------------------------------------------------------------------- |
| `field` | `FieldSelectionMap!` | A selection map describing which fields from the entity type are needed |
-Use `@require` when a resolver in one subgraph needs data that another subgraph owns. The gateway handles the data fetching automatically. This shifts cross-service data dependencies from hidden runtime failures to validated build-time contracts.
+Use `@require` when a resolver in one subgraph needs data that another subgraph owns. The gateway handles the data fetching automatically. This shifts cross-service data dependencies from hidden runtime failures to validated build-time contracts. Fields in the selection map may carry constant arguments to select a specific variant (for example, `@require(field: "dimension(unit: METRIC)")`); argument values must be constant literals (no variables), must match the field's argument definitions, and all required arguments must be supplied. Argument errors surface as `REQUIRE_INVALID_FIELDS`.
**Example -- scalar requirement:**
@@ -290,7 +292,7 @@ directive @provides(fields: FieldSelectionSet!) on FIELD_DEFINITION
| -------- | -------------------- | -------------------------------------------------------------------------------------------------- |
| `fields` | `FieldSelectionSet!` | A field selection set describing the subfields of the returned type that this subgraph can resolve |
-This is a query-planning optimization. When a client requests provided subfields through this particular field path, the gateway resolves them from the current subgraph instead of making a separate call. Fields referenced in `@provides` must be marked `@external` on the return type.
+This is a query-planning optimization. When a client requests provided subfields through this particular field path, the gateway resolves them from the current subgraph instead of making a separate call. Fields referenced in `@provides` must be marked `@external` on the return type. Fields in a `@provides` selection must not have arguments; composition reports any argument usage as `PROVIDES_FIELDS_HAS_ARGUMENTS`.
**Example:**
diff --git a/website/content/docs/fusion/entities-and-lookups.md b/website/content/docs/fusion/entities-and-lookups.md
index ee17b77ac64..0e7671be44b 100644
--- a/website/content/docs/fusion/entities-and-lookups.md
+++ b/website/content/docs/fusion/entities-and-lookups.md
@@ -352,6 +352,8 @@ The `@key(fields: "id")` directive explicitly declares that `Product` is identif
The `fields` value uses GraphQL field names, not C# member names.
+Key fields may supply constant arguments to select a specific variant of a field. For example, `@key(fields: "id(scope: LOCAL)")` selects the `id` field with the constant argument `scope: LOCAL`. Argument values must be constant literals (no variables), must match the field's declared argument definitions, and all required arguments must be supplied.
+
An entity can have multiple keys. Each `@key` directive on a type represents one key.
**GraphQL schema with scalar composite key**
diff --git a/website/content/docs/fusion/index.md b/website/content/docs/fusion/index.md
index 4ce5b451869..25741ab2774 100644
--- a/website/content/docs/fusion/index.md
+++ b/website/content/docs/fusion/index.md
@@ -1,5 +1,6 @@
---
-title: "Introduction"
+title: Fusion
+metaTitle: "Fusion: Federated GraphQL Gateway"
description: "Fusion is ChilliCream's GraphQL gateway for composing multiple services into one API, implementing the GraphQL Composite Schemas spec with build-time validation."
---
diff --git a/website/content/docs/hotchocolate/defining-a-schema/directives.md b/website/content/docs/hotchocolate/defining-a-schema/directives.md
index 165612c4155..0b505e2e171 100644
--- a/website/content/docs/hotchocolate/defining-a-schema/directives.md
+++ b/website/content/docs/hotchocolate/defining-a-schema/directives.md
@@ -306,6 +306,186 @@ public class FooType : ObjectType
Since the directive instance that we have added to our type is now a strong .NET type, we don't have to fear changes to the directive structure or name anymore.
+## Directives on Directive Definitions
+
+A directive definition is itself a schema element, so it can carry directives. You can use this to mark a directive definition as deprecated or to attach metadata to it, in the same way you annotate object types, fields, or enum values.
+
+To apply a directive to a directive definition, that directive must declare the `DIRECTIVE_DEFINITION` location.
+
+### Declaring a Directive That Targets Directive Definitions
+
+A directive can only be applied to a directive definition when its own definition includes the `DIRECTIVE_DEFINITION` location.
+
+
+
+```csharp
+public class OnDirectiveDefinitionType : DirectiveType
+{
+ protected override void Configure(IDirectiveTypeDescriptor descriptor)
+ {
+ descriptor.Name("onDirectiveDefinition");
+ descriptor.Location(DirectiveLocation.DirectiveDefinition);
+ }
+}
+```
+
+
+
+
+Call `Deprecated(...)` on the descriptor.
+
+```csharp
+public class OldDirectiveType : DirectiveType
+{
+ protected override void Configure(IDirectiveTypeDescriptor descriptor)
+ {
+ descriptor.Name("old");
+ descriptor.Location(DirectiveLocation.Object);
+ descriptor.Deprecated("Use @custom instead.");
+ }
+}
+```
+
+
+