GraphQLを使用していると、「Variable "$X" got invalid value; Expected type "Y"」というエラーに遭遇することがあります。このエラーは、GraphQLクエリやミューテーションに渡された変数の型が、スキーマで定義された型と一致しない場合に発生します。本記事では、このエラーの原因と解決方法について詳しく解説します。

エラーの原因

このエラーは主に以下の理由で発生します:

1. 変数の型が間違っている

2. 必須フィールドが欠落している

3. 列挙型の値が無効

4. 入力オブジェクトの構造が正しくない

解決方法

1. 変数の型を確認する

まず、クエリやミューテーションで使用している変数の型が、スキーマで定義されている型と一致しているか確認しましょう。例えば、整数型(Int)を期待しているところに文字列(String)を渡していないか確認します。

# 正しい例
mutation ($id: Int!) {
  deleteUser(id: $id)
}

# 間違った例(エラーの原因)
mutation ($id: String!) {
  deleteUser(id: $id)
}

2. 必須フィールドを確認する

スキーマで必須とされているフィールドが、すべて含まれているか確認します。必須フィールドは通常、感嘆符(!)で示されます。

# スキーマ定義
type User {
  id: ID!
  name: String!
  email: String
}

# 正しい例
mutation ($user: UserInput!) {
  createUser(user: $user)
}

# 間違った例(nameフィールドが欠落)
{
  "user": {
    "id": "123",
    "email": "user@example.com"
  }
}

3. 列挙型の値を確認する

列挙型(Enum)を使用している場合、その値がスキーマで定義された選択肢の中に含まれているか確認します。

# スキーマ定義
enum UserRole {
  ADMIN
  USER
  GUEST
}

# 正しい例
mutation ($role: UserRole!) {
  setUserRole(role: $role)
}

# 間違った例(無効な値)
{
  "role": "SUPERUSER"
}

4. 入力オブジェクトの構造を確認する

複雑な入力オブジェクトを使用している場合、その構造がスキーマの定義と一致しているか確認します。ネストされたオブジェクトや配列の形式に特に注意が必要です。

# スキーマ定義
input AddressInput {
  street: String!
  city: String!
  country: String!
}

input UserInput {
  name: String!
  email: String!
  address: AddressInput!
}

# 正しい例
mutation ($user: UserInput!) {
  createUser(user: $user)
}

# 正しい入力値
{
  "user": {
    "name": "John Doe",
    "email": "john@example.com",
    "address": {
      "street": "123 Main St",
      "city": "Anytown",
      "country": "USA"
    }
  }
}

デバッグのヒント

1. GraphQLのプレイグラウンド(GraphiQL等)を使用して、クエリやミューテーションをテストします。

2. クライアントサイドのコードで、変数の型や値を確認します。

3. サーバーサイドのログを確認し、受け取った変数の内容を検証します。

4. スキーマの定義を再確認し、クライアントサイドの実装と一致しているか確認します。

まとめ

「Variable "$X" got invalid value; Expected type "Y"」エラーは、GraphQLの型システムによるバリデーションエラーです。このエラーを解決するには、変数の型、必須フィールド、列挙型の値、そして入力オブジェクトの構造を注意深く確認する必要があります。適切なデバッグ手法を用いることで、エラーの原因を特定し、迅速に解決することができます。

GraphQLの型安全性は、アプリケーションの堅牢性を高める重要な特徴です。このエラーを適切に処理することで、より信頼性の高いアプリケーションを開発することができます。