Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Unsure how to resolve Missing field while writing result error when using subscriptions #8677

Closed
blehoux17 opened this issue Aug 20, 2021 · 73 comments
Assignees
Labels
🏓 awaiting-contributor-response requires input from a contributor 🔍 investigate Investigate further 🛎 subscriptions

Comments

@blehoux17
Copy link

We've implement subscriptions in our application using the useSubscription hook and since upgrading from version 3.3.21 to 3.4.7 we've started to see errors around Missing field.... To be clear we realize these errors have likely always existed, but now they're being surfaced.

We see the following error Missing field 'domainObject' while writing result {} on initial page load when the subscription is registered. We believe that this happens because the first response from the subscription is an empty object. The subscriptions themselves work fine, this only seems to be an issue when they're initially registered. We'd like to resolve this issue and remove the errors from the console, but have so far been unsuccessful.

We tried to update the fetchPolicy and found that setting it to no-cache removed the error, but this stopped the cache from being updated at all, which defeats the purpose.

Shown below is a snippet of the code that we've implemented. Some of the subscriptions allow apollo to do the cache updating on its own (OnObjectUpdated) while with others (OnObjectDeleted) we capture the return data and manually make a change to the cache. In both cases we see the Missing field error. For the OnObjectDeleted subscription, we added a guard in our callback function because when the subscription is registered we receive data as an empty object.

subscription OnObjectDeleted {
  objectDeleted {
    object {
      id
    }
  }
}
const removeObjectFromCache = ({ subscriptionData: { data } }) => {
  if (!data || !data.objectDeleted) return;

  removeObject(data.objectDeleted.object.id, client);
};

useSubscription(OnObjectDeleted, { onSubscriptionData: removeObjectFromCache });
useSubscription(OnObjectUpdated);

We're looking to see if anyone has encountered this and if so how it was resolved.

Thanks!

@masterkain
Copy link

masterkain commented Aug 30, 2021

yeah I can confirm I have the same issue on initial page subscription, using Vue + ActionCable

subscribeToMore(() => ({
  document: USER_APP_CREATED,
  variables: {
    gravatarSize: 24,
  },
  updateQuery: (oldData, { subscriptionData }) => {
    if (Object.keys(subscriptionData.data).length === 0) {
      return { ...oldData };
    }

stacktrace:

Screenshot 2021-08-30 at 02 09 08

"@apollo/client": "^3.4.8",
"@vue/apollo-composable": "^4.0.0-alpha.14",
"@vue/apollo-util": "^4.0.0-alpha.14",

@benjamn benjamn self-assigned this Aug 30, 2021
@hsavit1
Copy link

hsavit1 commented Sep 3, 2021

also having this issue since upgrading from 3.4-beta-0 to 3.4.10

@Angulo66
Copy link

Angulo66 commented Sep 7, 2021

i have the same issue, using "@apollo/client": "^3.3.18" "react-native": "0.64.0",

@benjamn
Copy link
Member

benjamn commented Sep 9, 2021

@blehoux17 I agree this is not an actionable or useful warning (in this particular case), and we should find a way to hide it.

I'm collecting various subscription-related issues using this label, in case you have any others you think deserve a(nother) look. Hopefully this issue will get fixed in the process, but I've labeled it to be sure.

@rebz
Copy link

rebz commented Sep 21, 2021

I too am seeing this error surface after upgrading this morning...

Original versions.

    "@apollo/client": "^3.2.1",
    "@vue/apollo-composable": "^4.0.0-alpha.14",

Upgraded versions.

    "@apollo/client": "^3.4.13",
    "@vue/apollo-composable": "^4.0.0-alpha.15",

@mvaivre
Copy link

mvaivre commented Sep 21, 2021

Also getting this error now (after upgrading) while executing cache.writeQuery (but the cache seems to be properly updated). I'm not using subscriptions.

@camilo-perilla-globant
Copy link

Also getting the error using useQuery and MockedProvider

"@apollo/client": "^3.4.13"

@Venryx
Copy link

Venryx commented Sep 23, 2021

Getting the same issue with apollo-client 3.5.0-beta.4.

Here is the relevant line in the source code, for those wondering:

invariant.error(`Missing field '${

Not really sure what I'm supposed to do to resolve the issue. (I know one way to solve it is to make sure the server returns a value for every field that Apollo is aware of; however I don't want to have to do that, because the field is already marked as optional in the GraphQL defined on the server, so I want Apollo to be compatible with that without needing server-side workarounds)

EDIT: Found a temporary fix:

apolloClient = new ApolloClient({
	[...]
	cache: new InMemoryCache({
		typePolicies: {
			// temp fix
			MyClass: {
				fields: {
					missingField1(rawVal: boolean, {args}) { return rawVal ?? null; },
					missingField2(rawVal: string, {args}) { return rawVal ?? null; },
				},
			},
		},
	}),
});

EDIT2: Nevermind, that seems not to have fixed it -- at least not reliably.

@xprazak2
Copy link

Also getting the error using useQuery and MockedProvider

"@apollo/client": "^3.4.13"

Same.

@glekner
Copy link

glekner commented Oct 2, 2021

same

@jamesopti
Copy link
Contributor

Hitting this too since we upgraded to "@apollo/client": "^3.4.9"

@KranzAklilu
Copy link

KranzAklilu commented Oct 10, 2021

same using "@apollo/client": "^3.3.12"

@hatched-danny
Copy link

hatched-danny commented Oct 12, 2021

+1 - "@apollo/client": "^3.4.10"

@sahanatroam
Copy link

+1 same

@sahanatroam
Copy link

Also getting the error using useQuery and MockedProvider

"@apollo/client": "^3.4.13"

same issue

@mheimark
Copy link

Running into this on "@apollo/client": "^3.4.16"

@aquelehugo
Copy link

Maybe it helps someone facing that in tests:

It happened with me because a mocked resolver had an exception inside.
In my case, I was accessing a property from the first item of an array inside the resolver and the array was empty.
The error in the resolver didn't show up, but I had that message from Apollo. When I added a validation for the item existence, the error went away.

@fauxparse
Copy link

I think I can make the error go away by making the field optional in my Subscription type:

type Subscription {
  """
  this field shows the error
  """
  joinedSession(sessionId: ID!): JoinedSessionPayload!

  """
  this one doesn't
  """
  leftSession(sessionId: ID!): LeftSessionPayload
}

In my case, I'm using graphql-ruby, so the solution was adding null: true to the field in my SubscriptionType class.

I do still get an onSubscriptionData fire with the initial (empty) payload, but as long as I check that I'm golden.

HTH!

@fauxparse
Copy link

I think I can make the error go away by making the field optional in my Subscription type:

Today it is not working 😔

@vpaul18
Copy link

vpaul18 commented Oct 30, 2021

So what's a fix to this problem ? I don't know if you experience the same behaviour, but my subscription doesn't subscribe because of this , which is quite a major problem ....

@IShinkarenko
Copy link

The same issue - "@apollo/client": "^3.4.16",

@jcook-gresham
Copy link

Also getting the error using useQuery and MockedProvider

"@apollo/client": "^3.4.13"

It seems like there is no ability to have an empty subscription mock, for when we want to only test a Query.

If the subscription isn't included in the mocks prop provided to MockedProvider, I get:
No more mocked responses for the query: subscription

If the subscription is included but with no data. something like this:

    {
        request: {
            query: SUBSCRIPTION_,
            variables: {},
        },
        result: {
            data: undefined,
        },
    },

Then Apollo will complain with:
Missing field while writing result

Can we get someway of ignoring subscriptions or providing a empty mock, to fix this error?

@fvalles
Copy link

fvalles commented Nov 29, 2021

Hi everyone! I faced this issue a few weeks ago. In my case, the error was produced by a missing property in a mocked object used by a test. E.g.:

Error:

console.error
    Missing field 'name' while writing result {
      "id": "1",
      "colorHex": "white"
    }

Mocked object:

export const mockedObject: ObjectType = { ...otherProps, category: { colorHex: '#745EA8', id: '11', }, };

In this example, the 'name' property was missing in the mock used by the test, which has a type of:

interface Category {
  id: string;
  name: string;
  colorHex: string;
}

Solution: Make the property optional, or add a mocked value for the mocked object

@Oliver-ke
Copy link

Hi everyone still facing this issue after upgrading @apollo/client to 3.5.6,

Missing field 'id' while writing result {
  "property": value,
....

If anyone has a working fix, please kindly share.

@efstathiosntonas
Copy link
Contributor

efstathiosntonas commented Jan 13, 2022

Not sure if it's the best solution but this eliminated the error:

error is: ExceptionsManager.js:184 Missing field 'chat_channel' while writing result {}

updateQuery: (prev, { subscriptionData }) => {
        if (Object.keys(prev || {}).length === 0) {
          // there's nothing in cache, return empty array otherwise crash!
          return { chat_channel: [] }; <---------- instead of return prev;
        }

@vicky-holcomb
Copy link

+1 same

@yahuio
Copy link

yahuio commented Feb 15, 2022

+1 same "@apollo/client": "^3.3.21",

@TheDutchCoder
Copy link

I previously solved this issue here: #8677 (comment)

But now it has come back because of a subscription that doesn't contain the full object, only updated parts.
In our case we have something like:

// Account
{
 id,
 name,
 verified
}

// Data from subscription
{
  id,
  name
}

Apollo, for unknown reasons, complains about verified missing from the response, which makes no sense. I really hope Apollo doesn't expect full DB row dumps on every subscription, that would be hugely wasteful.

It also just appeared a few days ago but I don't remember upgrading anything...

@gciluffo
Copy link

gciluffo commented Sep 19, 2022

This error is super misleading. In our case we had defined schema incorrectly. This error occurred when the actual field we were querying for during runtime didnt match up with the schema. Specifically it had to with returning a string when the type in the graph schema was Url. Changing to String in schema resolved the issue.

@csandanov
Copy link

csandanov commented Oct 11, 2022

I get this error when I manually update cache via writeQuery.

To clarify the use case for maintainers, I have two types:

type Project {
    id: Int!
    name: String!
}

type App {
    id: Int!
    project: Project!
}

First I fetch projects with all fields:

query projects {
    projects {
        id
        name
    }
}

Then I manually update cache via writeQuery for the following query:

query apps {
    apps {
        id
        project {
            id
        }
    }
}

I'll get Missing field 'name' while writing result error because the nested Project doesn't contain name field. This in turn prevents my cache updates which causes all kinds of new issues.

I hoped I could fix it via typePolicies's merge but the error happens before merge even called. So for now I have to fetch nested types with all fields for my cache writes.

I kiiiinda understand why this is the error (to be explicit about data updates/merge) and not a warning but I would really like to have a global option to make it a warning (or just ignore it completely), so my cache writes would go through and I would still be able to define the behaviour (e.g. use existing value if incoming is missing) in typePolicies's merge.

I have had this issue for a while now and it's still there in 3.7.0

@ragafus
Copy link

ragafus commented Oct 13, 2022

I'm still facing this issue with "@apollo/client": "3.7.0", using useQuery with relay style pagination.
It's a bit scary how an undefined value can break the cache and the pagination.

Given these two types

type MainSkills =  {
  hard?: string;
  soft?: string;
}

type User = {
  id
  name
  skills?: MainSkills
}

I use two fragments for the type User

fragment UserBasicData {
  id
  name
}

fragment UserFullData {
  id
  name
  skills {
    hard
    soft
  }
}

The errors appears when the data from the fragment UserBasicData is already stored in the cache and the data is refreshed with the data from UserFullData.

@vxm5091
Copy link

vxm5091 commented Oct 27, 2022

+1 on "@apollo/client": "3.6.8"

Same scenario as @ragafus

@ryancrunchi
Copy link

+1 with 3.7.0
Also having issue with subscription creating cache data for a different entity if the typename does not match the one of initial query.
For example, query __typename is User
subscription __typename is UserUpdate
apollo creates a cache entry for UserUpdate, even with fetch policy no-cache set on subscription
even if onData calls a cache.updateQuery on initial query

@medemi68
Copy link

How has nobody from Apollo commented on this post. Am I missing something?

@medemi68
Copy link

medemi68 commented Nov 1, 2022

  updateQuery: (prev, { subscriptionData }) => {
        if (!subscriptionData.data) return prev;

        const newFeedItem = subscriptionData.data.sortedMessageSubscription;

        const newMessagesCached = {
          sortedMessages: prev.sortedMessages.concat(newFeedItem),
        };

        return Object.assign({}, prev, newMessagesCached);
      },

I solved mine by changing the code as above... where sortedMessages is the name of the field saved in the cache I really hope this helps someone

This solved the problem for me.

@Abdelmonimsamadi
Copy link

i have the same issue here

@bxter
Copy link

bxter commented Nov 21, 2022

me too, any one can help this?

image

@olegchursin
Copy link

Same here. apollo-angular v3.0.0

@PanKarton
Copy link

Menaged to fix it somehow. I had this bug in that function

fetchMore({
      // Update page variable based on
      variables: {
        page: endCursor,
        pageSize: 1,
      },
      // Merge old data with new data and return(update) current data
      updateQuery: (prevResult, { fetchMoreResult }) => {
        if (!fetchMoreResult) return prevResult;
        const prevData = prevResult.newsPosts.data;
        const newData = fetchMoreResult.newsPosts.data;
        const mergedData = [...prevData, ...newData];

        return {
          newsPosts: { data: mergedData },
        };
      },
    });

Problem was that i returned only mergedData instead of updating just part of the object where my posts were stored, so I was overriding whole data object and compiler couldn't find newsPosts in data object, because my data object was actually mergedData array. Maybe it will help sameone idk xD

@apss-pohl
Copy link

I am running into this issue because i have to use an await within "updateQuery". As soon as i set "updateQuery" async the issue pop`s up.
I could not find any guidance on that. Cant i use async at all in this context?

@rebz
Copy link

rebz commented Jan 21, 2023

#8677 (comment)

I too am seeing this error surface after upgrading this morning...

Original versions.

    "@apollo/client": "^3.2.1",
    "@vue/apollo-composable": "^4.0.0-alpha.14",

Upgraded versions.

    "@apollo/client": "^3.4.13",
    "@vue/apollo-composable": "^4.0.0-alpha.15",

Not sure if it's the best solution but this eliminated the error:

error is: ExceptionsManager.js:184 Missing field 'chat_channel' while writing result {}

updateQuery: (prev, { subscriptionData }) => {
        if (Object.keys(prev || {}).length === 0) {
          // there's nothing in cache, return empty array otherwise crash!
          return { chat_channel: [] }; <---------- instead of return prev;
        }

Solved my issue. Didn't realize it was due to a Subscription lacking the a field the query originally contained. I tweaked the return data on updateQuery to combine the incoming subscription data with the previously known data. So now I can maintain the missing field data while getting updates on the data I care about.

@jnsandrew
Copy link

jnsandrew commented Feb 1, 2023

I had this error appear using MockedProvider / storybook-addon-apollo-client while mocking a specific query. It was complaining about Missing field icon.... In my case the mocked data being returned was in the wrong format:

Query:

export default gql`
  query GetIconQuery($iconId: String!) {
    icon(iconId: $iconId) {
      url
    }
  }
`;

Mocked data that was erroring:

{
   request: {
     query: GetIconQuery,
      variables: {
        iconId: icon.id,
      },
    },
    result: {
     data: {
       url: `icon.svg`,
     },
   },
}

The fix is to change result.data.url with result.data.icon.url because that's the name of the query

{
   request: {
     query: GetIconQuery,
      variables: {
        iconId: icon.id,
      },
    },
    result: {
     data: {
       icon: {
         url: `icon.svg`,
       }
     },
   },
}

@alessbell
Copy link
Contributor

Hi everyone 👋 Can anyone share a runnable reproduction here? With the number of comments—many of which seem to have been resolved by ensuring the data returned matches the shape of the initial request—it's difficult to determine whether there is anything actionable on our end.

We have a CodeSandbox and forkable GitHub repo with a subscriptions.tsx already configured. Thanks!

@alessbell alessbell added the 🏓 awaiting-contributor-response requires input from a contributor label Apr 3, 2023
@at2706
Copy link

at2706 commented May 1, 2023

Hello. I'm getting this error when mocking query results. Here's a CodeSandbox example:
https://codesandbox.io/s/apollo-client-missing-field-error-srr15m

@bcgilliom
Copy link

@alessbell adding every field does solve the issue, but it would be super nice to be able to suppress that warning in tests so nullable fields we don't care about for a test don't need to be specified

@hshoja
Copy link

hshoja commented Aug 3, 2023

fixed the error by adding fetchPolicy: "no-cache" in useSubscription

"@apollo/client": "3.7.16",
"@rails/actioncable": "7.0.6",
 "graphql-ruby-client": "1.11.8",

@jcpeden
Copy link

jcpeden commented Oct 13, 2023

Thanks for sharing @hshoja, this fixed the issue for me when testing with React Testing Library and

@AndreiRailean
Copy link

AndreiRailean commented Apr 5, 2024

We faced a similar issue and upon close investigation, we ended up blaming it on ActionCable and how graphql-ruby gem works with it. The main issue is that upon initial subscription, it returns data={} because that's how empty result gets serialised by .to_h call in ruby, i.e. it when result.data=nil, and the code runs result.to_h, you end up with result: data: {}.

This appears to have been a deliberate change introduced to better support Relay in 2019 in rmosolgo/graphql-ruby#2536

https://github.com/rmosolgo/graphql-ruby/pull/2536/files#diff-a1ea5af1a78917fa653eff83d9ae72180fabd3d9cf616f14dd1871739963cd73L44

We ended up changing our implementation on the ruby side, which ended up setting data: null. This stops Apollo client from erroring because of type mismatch. We didn't want to manually introduce a type override for each subscription we add. This approach allows us to support initial subscription result if we ever wanted to.
image

And we went from this in our cable stream
image

To this
image

And there were no more errors and all subscriptions kept on working as expected.

If you're running into this error, it may help to consider adjusting the server, rather than waiting for Apollo client to ever change to support this. The issue is really with what restrictions ActionCable places on graphql-ruby for delivering subscriptions. By default, graphql-ruby is conffigured to NOT send a payload for initial subscription, but when it comes to ActionCable channels, it appears unavoidable that something will be sent and in this case it ends up being formatted incorrectly.

cc @rmosolgo

@rikas
Copy link

rikas commented Apr 5, 2024

@AndreiRailean I had exactly the same issue but I didn't have to fiddle around with graphql-ruby internals.

When I left the default subscribe method in one of my subscriptions I was getting the error described in this thread (because of data = {}) but then I tried to just override the subscribe to return nil and apparently that worked.

class MySubscription < BaseSubscription
  argument :whatever_argument, String, required: true

  def subscribe(whatever_argument:)
    nil
  end
end

This is now sending data = null in the cable connection.

Hope that helps people using graphql-ruby.

@melissap-nulogy
Copy link

@AndreiRailean I had exactly the same issue but I didn't have to fiddle around with graphql-ruby internals.

When I left the default subscribe method in one of my subscriptions I was getting the error described in this thread (because of data = {}) but then I tried to just override the subscribe to return nil and apparently that worked.

class MySubscription < BaseSubscription
  argument :whatever_argument, String, required: true

  def subscribe(whatever_argument:)
    nil
  end
end

This is now sending data = null in the cable connection.

Hope that helps people using graphql-ruby.

When I do this I get Cannot return null for non-nullable field Subscription.objectDeleted and the subscriptions stop working.

@tintin10q
Copy link

Can someone close this issue? It is not about the same thing anymore as the initial issue.

@jerelmiller
Copy link
Member

Hey all 👋

It seems this might have been solved or answered throughout this thread. If there is still an issue, please open a new issue and we'd be happy to take a look. Thanks!

Copy link
Contributor

github-actions bot commented Jan 9, 2025

Do you have any feedback for the maintainers? Please tell us by taking a one-minute survey. Your responses will help us understand Apollo Client usage and allow us to serve you better.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🏓 awaiting-contributor-response requires input from a contributor 🔍 investigate Investigate further 🛎 subscriptions
Projects
None yet
Development

No branches or pull requests