facebook/relay · error

requestSubscription: Must use Subscription operation

Error message

requestSubscription: Must use Subscription operation

What it means

requestSubscription requires the tagged node passed in config.subscription to be a subscription operation. It checks subscription.params.operationKind and throws for queries or mutations, since only subscriptions support the long-lived executor/streaming semantics.

Source

Thrown at packages/relay-runtime/subscription/requestSubscription.js:62

export type GraphQLSubscriptionConfig<TVariables, TData, TRawResponse> =
  Readonly<{
    configs?: Array<DeclarativeMutationConfig>,
    cacheConfig?: CacheConfig,
    subscription: GraphQLSubscription<TVariables, TData, TRawResponse>,
    variables: NoInfer<TVariables>,
    onCompleted?: ?() => void,
    onError?: ?(error: Error) => void,
    onNext?: ?(response: ?TData) => void,
    updater?: ?SelectorStoreUpdater<TData>,
  }>;

function requestSubscription<TVariables extends Variables, TData, TRawResponse>(
  environment: IEnvironment,
  config: GraphQLSubscriptionConfig<TVariables, TData, TRawResponse>,
): Disposable {
  const subscription = getRequest(config.subscription);
  if (subscription.params.operationKind !== 'subscription') {
    throw new Error('requestSubscription: Must use Subscription operation');
  }
  const {configs, onCompleted, onError, onNext, variables, cacheConfig} =
    config;
  const operation = createOperationDescriptor(
    subscription,
    variables,
    cacheConfig,
  );

  warning(
    !(config.updater && configs),
    'requestSubscription: Expected only one of `updater` and `configs` to be provided',
  );

  const {updater} = configs
    ? RelayDeclarativeMutationConfig.convert<$FlowFixMe>(
        configs,
        subscription,

View on GitHub (pinned to 668b1b85e0)

Solutions

  1. Pass an operation declared with graphql`subscription ... {...}`
  2. Use commitMutation for mutations or fetchQuery for queries instead
  3. Verify operationKind at the call site if the tag comes from a shared constant
  4. Enable Relay's typed graphql (relay-compiler) so mismatched kinds are caught at build time

Example fix

// before
requestSubscription(env, {subscription: graphql`query R { ... }`, variables});
// after
requestSubscription(env, {subscription: graphql`subscription S { ... }`, variables});
Defensive patterns

Strategy: validation

Validate before calling

const sub = getRequest(config.subscription);
if (sub.params.operationKind !== 'subscription') {
  throw new TypeError('requestSubscription requires a subscription operation, got ' + sub.params.operationKind);
}

Type guard

const isSubscriptionOp = (tag) => getRequest(tag).params.operationKind === 'subscription';

Try / catch

try {
  requestSubscription(env, config);
} catch (e) {
  if (e.message === 'requestSubscription: Must use Subscription operation') {
    throw new Error('config.subscription must be a graphql`subscription ...` operation');
  }
  throw e;
}

Prevention

When it happens

Trigger: Calling requestSubscription(env, {subscription: graphql`query ...` or `mutation ...`}) — the operation kind check fails.

Common situations: Reusing a query/mutation tag in a subscription config after refactoring; copy-pasting requestSubscription boilerplate without changing the operation; TypeScript not catching it because the tag is loosely typed.

Related errors


AI-assisted analysis of facebook/relay@668b1b85e0 (2026-09-02). Data as JSON: /api/errors/abcef50a019efc21. Report an issue: GitHub.