graphql-tools: Subscriptions sometimes fail with: "Cannot redefine property: Symbol(subschemaMap)"

Sometimes remote subscriptions fail with the error: “Cannot redefine property: Symbol(subschemaMap)” I am not sure what causes it, as sometimes I am able to send multiple events in a row, and sometimes I’m not.

What I do know:

  • My websockets executor is more-or-less the same as the one in the example.
  • The remote server passes the data correctly (ie a console.log in the next property of the subscriptionClient.subscribe does show the correct data, and the ws error handler is not called).
  • The error is sent over websocket, it’s not an error in a frontend library.
  • I don’t think this is an error in apollo-server-express or the subscriptions transport library, because they don’t have an instance of subschemaMap anywhere in their code.

At the moment I don’t have a 100% reliable reproduction because I don’t know what causes it. But I will investigate further tomorrow. If anyone has any immediate ideas where to look let me know in the meantime 😃

About this issue

  • Original URL
  • State: closed
  • Created 4 years ago
  • Reactions: 2
  • Comments: 26 (3 by maintainers)

Most upvoted comments

A fix for the bugs with batchDelegateToSchema is included within the latest release. Please let me know if problems persist, especially with the possibly related but separate bug with subscriptions. Thanks to all!

Same issue on our side when we use batch-delegate to delegate 2 times the same key.

We found 2 workarounds:

  • Using delegateToSchema instead of batchDelegateToSchema

  • Downgrade @graphql-tools/delegate to 7.0.6

    yarn.lock
    "@graphql-tools/batch-delegate@^7.0.0", "@graphql-tools/batch-delegate@^7.0.1":
    version "7.0.1"
    resolved "https://registry.yarnpkg.com/@graphql-tools/batch-delegate/-/batch-delegate-7.0.1.tgz#ad8452081c462047a8ff182d614d447051ffe023"
    integrity sha512-6oAmwzf9F2obUqpmoEVgwnomARmFQiHBC8X24LDbhJ7QJvhbrWqY101RArR4Jtb0zY6wpRtDNYuCIdzGoPR3LA==
    dependencies:
        "@graphql-tools/delegate" "^7.0.7"
        dataloader "2.0.0"
        tslib "~2.0.1"
    
    "@graphql-tools/batch-execute@^7.0.0":
    version "7.0.0"
    resolved "https://registry.yarnpkg.com/@graphql-tools/batch-execute/-/batch-execute-7.0.0.tgz#e79d11bd5b39f29172f6ec2eafa71103c6a6c85b"
    integrity sha512-+ywPfK6N2Ddna6oOa5Qb1Mv7EA8LOwRNOAPP9dL37FEhksJM9pYqPSceUcqMqg7S9b0+Cgr78s408rgvurV3/Q==
    dependencies:
        "@graphql-tools/utils" "^7.0.0"
        dataloader "2.0.0"
        is-promise "4.0.0"
        tslib "~2.0.1"
    
    "@graphql-tools/delegate@7.0.6", "@graphql-tools/delegate@^7.0.1", "@graphql-tools/delegate@^7.0.3", "@graphql-tools/delegate@^7.0.6":
    version "7.0.6"
    resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-7.0.6.tgz#dfead3ee89db9f6622ae159a699c4915a825cff0"
    integrity sha512-KqhES4UFOyEhNkvcyv12y9mklKX3eMa43xS6VbdiXlTqsXdzJ7BaXHFDZPhiMhFIEs070HQE38CGG12SREfTXg==
    dependencies:
        "@ardatan/aggregate-error" "0.0.6"
        "@graphql-tools/batch-execute" "^7.0.0"
        "@graphql-tools/schema" "^7.0.0"
        "@graphql-tools/utils" "^7.0.2"
        dataloader "2.0.0"
        is-promise "4.0.0"
        tslib "~2.0.1"
    
    "@graphql-tools/delegate@^7.0.7":
    version "7.0.7"
    resolved "https://registry.yarnpkg.com/@graphql-tools/delegate/-/delegate-7.0.7.tgz#276fd3f22183857c17ed0d37eac95f91bc982ac5"
    integrity sha512-2sze+CJxu37b4jcQ4fyj6ap9TMnx8+NBtApSs1nWIVENzPE2510aNTsBHgSdTwSeV/tVIFkAtZZAlMEGYGXzQA==
    dependencies:
        "@ardatan/aggregate-error" "0.0.6"
        "@graphql-tools/batch-execute" "^7.0.0"
        "@graphql-tools/schema" "^7.0.0"
        "@graphql-tools/utils" "^7.0.2"
        dataloader "2.0.0"
        is-promise "4.0.0"
        tslib "~2.0.1"
    
    "@graphql-tools/links@^7.0.3":
    version "7.0.3"
    resolved "https://registry.yarnpkg.com/@graphql-tools/links/-/links-7.0.3.tgz#e734d02b48038f3cfd80ecee0da28378ce699831"
    integrity sha512-if/o6H6Gjk7Ph2hZsBaUL1z95jeAMDdgAIA8RFxepXJAHLIcyufFvCoKxReeXhuG6C20FfLIVhDXeXdsQkezmQ==
    dependencies:
        "@graphql-tools/delegate" "^7.0.3"
        "@graphql-tools/utils" "^7.0.2"
        apollo-upload-client "14.1.2"
        cross-fetch "3.0.6"
        form-data "3.0.0"
        is-promise "4.0.0"
        tslib "~2.0.1"
    
    "@graphql-tools/load@^6.2.5":
    version "6.2.5"
    resolved "https://registry.yarnpkg.com/@graphql-tools/load/-/load-6.2.5.tgz#7dd0d34c8ce2cfb24f61c6beba2817d9afdd7f2b"
    integrity sha512-TpDgp+id0hhD1iMhdFSgWgWumdI/IpFWwouJeaEhEEAEBkdvH4W9gbBiJBSbPQwMPRNWx8/AZtry0cYKLW4lHg==
    dependencies:
        "@graphql-tools/merge" "^6.2.5"
        "@graphql-tools/utils" "^7.0.0"
        globby "11.0.1"
        import-from "3.0.0"
        is-glob "4.0.1"
        p-limit "3.0.2"
        tslib "~2.0.1"
        unixify "1.0.0"
        valid-url "1.0.9"
    
    "@graphql-tools/merge@^6.2.5", "@graphql-tools/merge@^6.2.6":
    version "6.2.6"
    resolved "https://registry.yarnpkg.com/@graphql-tools/merge/-/merge-6.2.6.tgz#f10b8958523687440536ecf166f2959d2f094d0f"
    integrity sha512-G6x0QlIzFHoJ3dyF9a4gxmBtaEYJ+EoAAGqXHsE/drRr58K1jscQdfKZdF1wZWZgxkgakHqgt1+oFMeQg/O6ug==
    dependencies:
        "@graphql-tools/schema" "^7.0.0"
        "@graphql-tools/utils" "^7.0.0"
        tslib "~2.0.1"
    
    "@graphql-tools/schema@^7.0.0", "@graphql-tools/schema@^7.1.2":
    version "7.1.2"
    resolved "https://registry.yarnpkg.com/@graphql-tools/schema/-/schema-7.1.2.tgz#5084eaef893719ad01329f77673d102e7710542e"
    integrity sha512-GabNT51ErVHE2riDH4EQdRusUsI+nMElT8LdFHyuP53v8gwtleAj+LePQ9jif4NYUe/JQVqO8V28vPcHrA7gfQ==
    dependencies:
        "@graphql-tools/utils" "^7.1.2"
        tslib "~2.0.1"
    
    "@graphql-tools/stitch@^7.1.4":
    version "7.1.4"
    resolved "https://registry.yarnpkg.com/@graphql-tools/stitch/-/stitch-7.1.4.tgz#67aeb0a278edeeb4ceacdcdd12e220f37465cbb6"
    integrity sha512-puoctxfcdHREsK9M9QVl3lA/QO01bMDvMbTDHNYSQ5zbKE9neuJOqg5iIg1cgePCdBoy7WnuIi/n40zSn4Jm5A==
    dependencies:
        "@graphql-tools/batch-delegate" "^7.0.0"
        "@graphql-tools/delegate" "^7.0.6"
        "@graphql-tools/merge" "^6.2.6"
        "@graphql-tools/schema" "^7.1.2"
        "@graphql-tools/utils" "^7.1.2"
        "@graphql-tools/wrap" "^7.0.3"
        is-promise "4.0.0"
        tslib "~2.0.1"
    
    "@graphql-tools/url-loader@^6.7.1":
    version "6.7.1"
    resolved "https://registry.yarnpkg.com/@graphql-tools/url-loader/-/url-loader-6.7.1.tgz#ce4d2284b702a360d928e74e7f989d8579f0d9f6"
    integrity sha512-7NJ1G5diJAuWYZszQf0mNwPipVMOjIIMteNkutdExBq4CgN0V1xa3/iC25CUrI7sZiq+D367zZNONmKf+3bA2Q==
    dependencies:
        "@graphql-tools/delegate" "^7.0.1"
        "@graphql-tools/utils" "^7.1.5"
        "@graphql-tools/wrap" "^7.0.4"
        "@types/websocket" "1.0.1"
        cross-fetch "3.0.6"
        eventsource "1.0.7"
        extract-files "9.0.0"
        graphql-upload "^11.0.0"
        graphql-ws "3.1.0"
        is-promise "4.0.0"
        isomorphic-form-data "2.0.0"
        isomorphic-ws "4.0.1"
        sse-z "0.3.0"
        sync-fetch "0.3.0"
        tslib "~2.0.1"
        valid-url "1.0.9"
        ws "7.4.1"
    
    "@graphql-tools/utils@^7.0.0", "@graphql-tools/utils@^7.0.2", "@graphql-tools/utils@^7.1.2", "@graphql-tools/utils@^7.1.4", "@graphql-tools/utils@^7.1.5":
    version "7.1.5"
    resolved "https://registry.yarnpkg.com/@graphql-tools/utils/-/utils-7.1.5.tgz#82eb9fd1d796bf9455ccf8f3d8775674a4582eb3"
    integrity sha512-utJgoKJNhAUz0i+MGF1uvz7i4fxxz1TE21c68R38Hs4kmXO6A6H5e18jwzGdjspyf3IZOS621fmN9GQPzIazHg==
    dependencies:
        "@ardatan/aggregate-error" "0.0.6"
        camel-case "4.1.2"
        tslib "~2.0.1"
    
    "@graphql-tools/wrap@^7.0.3", "@graphql-tools/wrap@^7.0.4":
    version "7.0.4"
    resolved "https://registry.yarnpkg.com/@graphql-tools/wrap/-/wrap-7.0.4.tgz#436fc1a8febe23e57036ae21be0476dc8e5d9984"
    integrity sha512-txBs0W4k3WR86aEzBYXtKdGeeUXCNdRNxjQA/95T6ywNYoM8pw2mvpoXrWOvzbeaH3zwhbHY7kwii4atrC9irg==
    dependencies:
        "@graphql-tools/delegate" "^7.0.7"
        "@graphql-tools/schema" "^7.1.2"
        "@graphql-tools/utils" "^7.1.4"
        is-promise "4.0.0"
        tslib "~2.0.1"
    

Is this regression test good to you?

import { batchDelegateToSchema } from '@graphql-tools/batch-delegate'
import { makeExecutableSchema } from '@graphql-tools/schema'
import { stitchSchemas } from '@graphql-tools/stitch'
import { graphql } from 'graphql'

describe('external object annotation with batchDelegateToSchema', () => {
  const networkSchema = makeExecutableSchema({
    typeDefs: `
      type Domain {
        id: ID!
        name: String!
      }
      type Network {
        id: ID!
        domains: [Domain!]!
      }
      type Query {
        networks(ids: [ID!]!): [Network!]!
      }
    `,
    resolvers: {
      Query: {
        networks: (_root, { ids }) =>
          ids.map((id) => ({ id, domains: [{ id: Number(id) + 3, name: `network${id}.com` }] })),
      },
    },
  })

  const postsSchema = makeExecutableSchema({
    typeDefs: `
      type Network {
        id: ID!
      }
      type Post {
        id: ID!
        network: Network!
      }
      type Query {
        posts(ids: [ID!]!): [Post]!
      }
    `,
    resolvers: {
      Query: {
        posts: (_root, { ids }) =>
          ids.map((id) => ({
            id,
            network: { id: Number(id) + 2 },
          })),
      },
    },
  })

  const gatewaySchema = stitchSchemas({
    subschemas: [{ schema: networkSchema }, { schema: postsSchema }],
    resolvers: {
      Post: {
        network: {
          selectionSet: '{ network { id } }',
          resolve(parent, _args, context, info) {
            return batchDelegateToSchema({
              key: parent.network.id,
              argsFromKeys: (ids) => ({ ids }),
              context,
              fieldName: 'networks',
              info,
              operation: 'query',
              schema: networkSchema,
            })
          },
        },
      },
    },
  })

  test('if batchDelegateToSchema can delegate 1 time an unique key', async () => {
    const { data } = await graphql(
      gatewaySchema,
      `
        query {
          posts(ids: [55]) {
            network {
              id
              domains {
                id
                name
              }
            }
          }
        }
      `,
    )

    expect(data?.posts).toEqual([
      {
        network: { id: '57', domains: [{ id: '60', name: 'network57.com' }] },
      },
    ])
  })

  test('if batchDelegateToSchema can delegate 2 times the same key', async () => {
    const result = await graphql(
      gatewaySchema,
      `
        query {
          posts(ids: [55, 55]) {
            network {
              id
              domains {
                id
                name
              }
            }
          }
        }
      `,
    )

    // Error: Cannot redefine property: Symbol(subschemaMap)
    expect(result.data?.posts).toEqual([
      {
        network: { id: '57', domains: [{ id: '60', name: 'network57.com' }] },
      },
      {
        network: { id: '57', domains: [{ id: '60', name: 'network57.com' }] },
      },
    ])
  })
})