All skills
apollographql avatar

/apollo-connectors

@55e7707 official
by Apollo GraphQLapollographql/skills115 stars
13

Guide for integrating REST APIs into GraphQL supergraphs using Apollo Connectors with @source and @connect directives. Use this skill when the user: (1) mentions "connectors", "Apollo Connectors", or "REST Connector", (2) wants to integrate a REST API into GraphQL, (3) references @source or @connect directives, (4) works with files containing "# Note to AI Friends: This is an Apollo Connectors schema".

Use this Skill: https://skilld.dev/gh/apollographql/skills/apollo-connectors

This session only. Nothing lands on disk.

referencestroubleshooting.md

≈2.1k tokens on demand. Your agent reads this file only when SKILL.md points to it.

Troubleshooting

Common errors and solutions when working with Apollo Connectors.

Table of Contents

No + Operator for Concatenation

Problem: Trying to concatenate strings with +.

# WRONG
fullName: firstName + " " + lastName

Solution: Use ->joinNotNull with an array.

# CORRECT
fullName: $([firstName, lastName])->joinNotNull(' ')

# With more parts
address: $([street, city, state, zip])->joinNotNull(', ')

Literal Values Require $()

Problem: Literal values in mappings without the $() wrapper.

# WRONG - Will not compose
body: "{ userId: $args.id }"
greeting: "Hello"
count: 42

Solution: Wrap literals in $().

# CORRECT
body: "$({ userId: $args.id })"
greeting: $("Hello")
count: $(42)
isActive: $(true)

No Array Indexing Syntax

Problem: Trying to use bracket notation for array access.

# WRONG
firstItem: items[0]
thirdItem: items[2]

Solution: Use array methods.

# CORRECT
firstItem: items->first
lastItem: items->last
thirdItem: items->get(2)
firstThree: items->slice(0, 3)

MISSING_ENTITY_CONNECTOR Error

Problem: An entity type is missing a @connect directive.

Error: MISSING_ENTITY_CONNECTOR
Entity "User" is missing a connector.

Cause: You've referenced a type as an entity (via stub or @key) but haven't defined how to resolve it.

Solution: Add @connect to the entity type.

# Add @connect to make it a resolvable entity
type User @connect(
  source: "api"
  http: { GET: "/users/{$this.id}" }
  selection: "id name email"
) {
  id: ID!
  name: String
  email: String
}

Or, if it shouldn't be an entity, remove the entity stub and inline the data.

INVALID_BODY Error

Problem: Request body not properly formatted.

Error: INVALID_BODY
Body must use literal syntax.

Cause: Object literal in body without $() wrapper.

# WRONG
body: "{ userId: $args.id }"

Solution: Use $() for object literals.

# CORRECT
body: "$({ userId: $args.id })"

# For nested objects
body: "$({ user: { id: $args.id, name: $args.name } })"

No == Operator

Problem: Using == for equality comparison.

# WRONG
isActive: status == "active"
is200: $status == 200

Solution: Use the ->eq method.

# CORRECT
isActive: status->eq("active")
is200: $status->eq(200)

For HTTP status checks with simple boolean returns:

# For DELETE operations that should return true on success
selection: "$(true)"

No Ternary Operator

Problem: Using ternary operator for conditional values.

# WRONG
result: condition ? valueA : valueB

Solution: Use null coalescing operators.

# Use ?? for null/undefined fallback
result: value ?? "default"

# Use ?! for undefined-only fallback (preserves null)
result: value ?! "fallback"

# Use ->match for value mapping
result: status->match(
  ["active", "Active User"],
  ["inactive", "Inactive User"],
  [@, "Unknown"]
)

Filter with Multiple Conditions

Problem: Using ->and inside filter or find.

# WRONG - @ changes meaning in nested method
items: $.list->filter(@.active->and(@.price->gt(10)))

Cause: The @ variable refers to different values in nested contexts.

Solution: Chain filter calls.

# CORRECT - Chain filters
items: $.list->filter(@.active)->filter(@.price->gt(10))

# For find
item: $.list->filter(@.active)->find(@.price->gt(10))

Circular Reference Error

Problem: Entity stubs create a circular dependency.

Error: Circular reference detected between Product and Review

Cause: Product has reviews, Review has product, both as entity stubs.

Solution: Use @inaccessible foreign key pattern.

type Product {
  id: ID!
  reviews: [Review] @connect(
    http: { GET: "/products/{$this.id}/reviews" }
    selection: "id rating text productId"  # Include FK
  )
}

type Review {
  id: ID!
  rating: Int
  text: String
  productId: ID! @inaccessible  # Hide from clients
  product: Product @connect(
    http: { GET: "/products/{$this.productId}" }
    selection: "id name"
  )
}

Headers Are Always Arrays

Problem: Accessing header value directly.

# WRONG - Headers are arrays
auth: $request.headers.authorization

Solution: Use ->first to get the first value.

# CORRECT
auth: $request.headers.authorization->first

# For headers with special characters
custom: $request.headers.'x-custom-header'->first

Unnecessary Root $

Problem: Using $ when selecting from root.

# WRONG - Unnecessary
selection: """
$ {
  id
  name
}
"""

Solution: Select fields directly.

# CORRECT
selection: """
id
name
"""

Use $ only when:

  • Accessing a nested path: $.results { id }
  • Using a method: $->first { id }

Wrong Federation/Connect Versions

Problem: Schema won't compose due to version mismatch.

Error: Incompatible federation and connect versions

Solution: Use the latest LTS Federation version together with the latest generally available Connectors spec that LTS supports. Use an experimental Connectors spec only when the user explicitly asks for it.

# CORRECT - current LTS; confirm against the docs before copying
extend schema
  @link(url: "https://specs.apollo.dev/federation/v2.15")
  @link(url: "https://specs.apollo.dev/connect/v0.3", import: ["@source", "@connect"])

See Version requirements for how to resolve the current LTS. Pin federation_version in supergraph.yaml to the latest patch of that Federation LTS (currently =2.15.2).

Entity Without Endpoint

Problem: Want to create an entity but there's no API endpoint for it.

Solution: Don't make it an entity. Use a regular type.

# If there's no /address/{id} endpoint, don't make it an entity
type Address {  # No @connect, no @key
  street: String
  city: String
  country: String
}

# Include it inline in the parent's selection
type User @connect(
  http: { GET: "/users/{$this.id}" }
  selection: """
  id
  name
  address {
    street
    city
    country
  }
  """
) {
  id: ID!
  name: String
  address: Address
}

Selection vs GraphQL Response

Problem: Test expectations don't match actual output.

Cause: connectorResponse in tests is the selection mapping result, not the final GraphQL response.

# apiResponseBody from REST API
apiResponseBody: |
  { "user_id": "123", "user_name": "Alice" }

# Selection mapping
selection: """
id: user_id
name: user_name
"""

# connectorResponse is the mapping result
connectorResponse: |
  { "id": "123", "name": "Alice" }

Note: No type conversion unless explicitly done with ->parseInt, ->toString, etc.

Batch Without API Support

Problem: Using $batch but API doesn't support batch requests.

Solution:

  1. Ask user if API has a batch endpoint
  2. If not, use non-batch pattern and accept N+1 queries
  3. Consider if the API can be modified to add batch support
# Non-batch (N+1)
type Product @connect(
  http: { GET: "/products/{$this.id}" }
  selection: "id name"
) {
  id: ID!
  name: String
}

# Batch (requires API support)
type Product @connect(
  http: {
    POST: "/products/batch"
    body: "ids: $batch.id"
  }
  selection: "id name"
) {
  id: ID!
  name: String
}

Source: SKILL.md on GitHub

1 warning6d5 checks · Risk SAFE
  • Gen Agent Trust Hub6d

    The skill is a comprehensive documentation and assistance tool for Apollo Connectors. It adheres to security best practices by using environment variables for secret management, restricted command execution via the rover CLI, and fetching resources from official vendor domains.

  • Socket6d

    No alerts

  • Snyk6d

    Risk: LOW · No issues

  • Runlayer7mo

    7/7 files flagged

  • ZeroLeaks5mo

    Score: 93/100 · 2 sections analyzed

Signed by skilld at 55e7707. This ties the file your Agent reads to that commit on GitHub. It does not review the instructions.

Last checked against GitHub yesterday.

Activeupdated last week
What it can do
Runs commands
metadata
{
  "author": "apollographql",
  "version": "1.0.1"
}
All 1 allowed tools
Bash(rover:*) Read Write Edit Glob Grep
Other metadata
compatibility
Requires rover CLI installed. Works with Claude Code and similar AI coding assistants.
  • graphql
  • apollo
  • rest-api
  • connectors
  • federation
  • schema
  • integration

README badge

README badge for apollographql/skills/apollo-connectors

Integrates REST APIs into GraphQL supergraphs using Apollo Connectors with @source and @connect directives. Targets the rover CLI workflow and follows a five-step process: research the API, implement the schema, validate with rover compose, execute with rover connector run, and test coverage.

Generated from the current SKILL.md.

What versions of Apollo federation and connectors does this skill support?
The skill uses federation v2.12 and connect v0.3 by default unless you specify otherwise.
Do I need rover CLI installed to use this skill?
Yes. The skill requires rover CLI installed and uses commands like `rover supergraph compose`, `rover connector run`, and `rover connector test`.
Can this skill integrate any REST API into GraphQL?
Yes. The skill handles REST API integration using @source and @connect directives, supporting GET/POST requests, headers, batching, and response field mapping.
Does this skill handle entity relationships and N+1 query patterns?
Yes. The skill creates entity relationships when ID fields are present and converts N+1 patterns using batching with the $batch variable.
What happens if composition or connector execution fails?
The skill follows a 5-step validation process that runs `rover supergraph compose` after schema changes and `rover connector run` before testing, catching errors before they reach production.

Generated from the current SKILL.md. These answers refresh after source changes.