All Variable Uses Defined
Formal Specification
- For each
operation
in a document
- For each variableUsage in scope, variable must be in operation ‘s variable list.
- Let fragments be every fragment referenced by that operation transitively
- For each
fragment
in
fragments
- For each variableUsage in scope of fragment , variable must be in operation ‘s variable list.
Explanatory Text
Variables are scoped on a per‐operation basis. That means that any variable used within the context of an operation must be defined at the top level of that operation
For example:
query variableIsDefined($atOtherHomes: Boolean) {
dog {
isHousetrained(atOtherHomes: $atOtherHomes)
}
}
is valid. $atOtherHomesis defined by the operation.
By contrast the following query is invalid:
query variableIsNotDefined {
dog {
isHousetrained(atOtherHomes: $atOtherHomes)
}
}
$atOtherHomesis not defined by the operation.
Fragments complicate this rule. Any fragment transitively included by an operation has access to the variables defined by that operation. Fragments can appear within multiple operations and therefore variable usages must correspond to variable definitions in all of those operations.
For example the following is valid:
query variableIsDefinedUsedInSingleFragment($atOtherHomes: Boolean) {
dog {
...isHousetrainedFragment
}
}
fragment isHousetrainedFragment on Dog {
isHousetrained(atOtherHomes: $atOtherHomes)
}
sinceisHousetrainedFragmentis used within the context of the operationvariableIsDefinedUsedInSingleFragmentand the variable is defined by that operation.
On the other hand, if a fragment is included within an operation that does not define a referenced variable, the query is invalid.
query variableIsNotDefinedUsedInSingleFragment {
dog {
...isHousetrainedFragment
}
}
fragment isHousetrainedFragment on Dog {
isHousetrained(atOtherHomes: $atOtherHomes)
}
This applies transitively as well, so the following also fails:
query variableIsNotDefinedUsedInNestedFragment {
dog {
...outerHousetrainedFragment
}
}
fragment outerHousetrainedFragment on Dog {
...isHousetrainedFragment
}
fragment isHousetrainedFragment on Dog {
isHousetrained(atOtherHomes: $atOtherHomes)
}
Variables must be defined in all operations in which a fragment is used.
query housetrainedQueryOne($atOtherHomes: Boolean) {
dog {
...isHousetrainedFragment
}
}
query housetrainedQueryTwo($atOtherHomes: Boolean) {
dog {
...isHousetrainedFragment
}
}
fragment isHousetrainedFragment on Dog {
isHousetrained(atOtherHomes: $atOtherHomes)
}
However the following does not validate:
query housetrainedQueryOne($atOtherHomes: Boolean) {
dog {
...isHousetrainedFragment
}
}
query housetrainedQueryTwoNotDefined {
dog {
...isHousetrainedFragment
}
}
fragment isHousetrainedFragment on Dog {
isHousetrained(atOtherHomes: $atOtherHomes)
}
This is becausehousetrainedQueryTwoNotDefineddoes not define a variable $atOtherHomesbut that variable is used byisHousetrainedFragmentwhich is included in that operation.