_helo friends,_
_Someone who can help me solve a problem in Apollo Graphql. I have implemented a search query that receives a parameter that is the title to search, the problem I have is that it shows me the following error:_
"message": "Abstract type Search must resolve to an Object type at runtime for field Query.search with value { id: \"avatar\", title: \"Avatar\", poster: \"https://pedropolis.tv/wp-content/uploads/2009/12/Avatar-150x150.jpg\", sinopsis: \"Jake Sully, un ex-marine confinado a una silla de ruedas, es reclutado para viajar al planeta Pandora, donde un consorcio corporativo est谩 extrayendo un mineral que ser谩 clave en la soluci贸n de ...\", type: \"pelicula\", extra: [[Object]] }, received \"undefined\". Either the Search type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function.",
_The return type of the search is a _union_ of the type _Series_ | _Movies__
鉂わ笍 _Any help will be more than received, I've been trying to solve the problem for a couple of weeks._
Query
const resolvers = require('./resolvers.js');
const {gql} = require('apollo-server');
const typeDefs = gql `
extend type Query{
search(query: String!): [Search!]!
}
union Search = Series | Movies
type Series{
id: String!
title: String!
sinopsis: String!
poster: String!
rating: String!
year: String!
extra: [SerieExtra!]!
}
type Movies{
id: String!
title: String!
sinopsis: String!
poster: String!
rating: String!
quality: String!
year: String!
extra: [MovieExtra!]!
}
type Episodes{
id: String!
title: String!
episode_name: String!
poster: String!
date: String!
quality: String!
sinopsis: String!
}
type VideoIframe{
iframe: Iframe
}
type Iframe{
option: Int
video_iframe: String
}
type SerieExtra {
channel: String!
first_air_date: String!
last_air_date: String!
total_seasons: String!
total_episodes: String
season_list: [SeasonList!] !
cast_members: CastMembers!
similar_series: [SimilarSeries!] !
}
type MovieExtra {
air_date: String!
country: String!
runtime: String!
rated: String!
cast_members: CastMembers!
similar_movies: [SimilarMovies!] !
}
// The information of the type SeasonList, CastMembers, SimilarSeries, SimilarMovies
// It was omitted since it would be a lot of information in the template .. for this discussion.
`;
module.exports = {
typeDefs,
resolvers
}
resolvers
const resolvers = {
Search:{
__resolveType(obj , context , info){
// .....
return null;
}
},
Query:{
search: async(_source , {query} , { dataSources}) =>{
return dataSources.API.search(query)
.then(doc => {
console.log(doc.content) // It correctly shows me the query data.
return doc.content;
});
},
}
};
Playground
query{
search(query: "avatar"){
... on Series{
id
}
... on Movies{
id
}
}
}
Error
{
"errors": [
{
"message": "Abstract type Search must resolve to an Object type at runtime for field Query.search with value { id: \"avatar\", title: \"Avatar\", poster: \"https://pedropolis.tv/wp-content/uploads/2009/12/Avatar-150x150.jpg\", sinopsis: \"Jake Sully, un ex-marine confinado a una silla de ruedas, es reclutado para viajar al planeta Pandora, donde un consorcio corporativo est谩 extrayendo un mineral que ser谩 clave en la soluci贸n de ...\", type: \"pelicula\", extra: [[Object]] }, received \"undefined\". Either the Search type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function.",
"locations": [
{
"line": 2,
"column": 3
}
],
"path": [
"search",
0
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"message": "Abstract type Search must resolve to an Object type at runtime for field Query.search with value { id: \"avatar\", title: \"Avatar\", poster: \"https://pedropolis.tv/wp-content/uploads/2009/12/Avatar-150x150.jpg\", sinopsis: \"Jake Sully, un ex-marine confinado a una silla de ruedas, es reclutado para viajar al planeta Pandora, donde un consorcio corporativo est谩 extrayendo un mineral que ser谩 clave en la soluci贸n de ...\", type: \"pelicula\", extra: [[Object]] }, received \"undefined\". Either the Search type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function.",
"locations": [
{
"line": 2,
"column": 3
}
],
"stacktrace": [
"GraphQLError: Abstract type Search must resolve to an Object type at runtime for field Query.search with value { id: \"avatar\", title: \"Avatar\", poster: \"https://pedropolis.tv/wp-content/uploads/2009/12/Avatar-150x150.jpg\", sinopsis: \"Jake Sully, un ex-marine confinado a una silla de ruedas, es reclutado para viajar al planeta Pandora, donde un consorcio corporativo est谩 extrayendo un mineral que ser谩 clave en la soluci贸n de ...\", type: \"pelicula\", extra: [[Object]] }, received \"undefined\". Either the Search type should provide a \"resolveType\" function or each possible type should provide an \"isTypeOf\" function.",
" at ensureValidRuntimeType (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:667:11)",
" at completeAbstractValue (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:660:42)",
" at completeValue (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:585:12)",
" at completeValue (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:557:21)",
" at completeValueCatchingError (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:495:19)",
" at C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:618:25",
" at Array.forEach (<anonymous>)",
" at forEach (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\iterall\\index.js:83:25)",
" at completeListValue (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:614:24)",
" at completeValue (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:573:12)"
]
}
}
}
],
"data": null
}
I'm getting a similar error. My guess is it has to do with the way I am stitching my schema. I only say this because I made a smaller version of my union example in a separate file where I keep my resolvers and type defs in the same file and it seemed to work.
Have you tried putting your type definitions and resolvers in the same file? I'm surprised more people haven't encountered this error.
I don't think you can just return null from your __resolveType method. I think you need to actually figure out if it is a Series or Movie and return that instead of null. See this page: https://www.apollographql.com/docs/apollo-server/schema/unions-interfaces/#union-type
I think I might have solved this issue. Inside your __resolveType make sure you're returning a string value that matches your union type.
For example, if your __resolveType decides a Series type then make sure your __resolveType returns 'Series'. Does that make sense?
Hello @luna215 and friends,
I still can't figure out the problem at all.
Here I leave the changes I have made and the new error that shows me. Apparently I'm close to getting the results ..
Playground
query{
search(query: "elite"){
... on SMovies{
id
title
poster
sinopsis
type
extra{
air_date
}
}
... on SSeries{
id
title
poster
sinopsis
type
extra{
channel
}
}
}
}
resolvers.js
const resolvers = {
Search:{
__solverType(obj , context , info){
if(obj.type === 'pelicula') return SMovies
if(obj.type === 'serie') return SSeries
}
},
SMovies:{
__isTypeOf(obj , context , info){
return Object.prototype.hasOwnProperty.call(obj, 'id');
}
},
SSeries:{
__isTypeOf(obj , context , info){
return Object.prototype.hasOwnProperty.call(obj, 'id');
}
},
MovieExtra:{
__isTypeOf(obj , context , info){
return Object.prototype.hasOwnProperty.call(obj , 'air_date')
}
},
SerieExtra:{
__isTypeOf(obj , context , info){
return Object.prototype.hasOwnProperty.call(obj , 'channel')
}
},
Query: {
search: async(_source , {query} , { dataSources}) =>{
return dataSources.API.search(query)
.then(doc => {
return doc.content;
})
},
}
};
module.exports = resolvers;
error
{
"errors": [
{
"message": "Expected value of type \"MovieExtra\" but got: { channel: \"Netflix\", first_air_date: \" First air date Oct. 05, 2018\", last_air_date: \" 脷ltima transmisi贸n Oct. 05, 2018\", total_seasons: \"1\", total_episodes: \"8\", season_list: [[Object], [Object]], cast_members: { creator: [Object], members_list: [Array] }, similar_series: [[Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], ... 2 more items] }.",
"locations": [
{
"line": 9,
"column": 7
}
],
"path": [
"search",
0,
"extra",
0
],
"extensions": {
"code": "INTERNAL_SERVER_ERROR",
"exception": {
"message": "Expected value of type \"MovieExtra\" but got: { channel: \"Netflix\", first_air_date: \" First air date Oct. 05, 2018\", last_air_date: \" 脷ltima transmisi贸n Oct. 05, 2018\", total_seasons: \"1\", total_episodes: \"8\", season_list: [[Object], [Object]], cast_members: { creator: [Object], members_list: [Array] }, similar_series: [[Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], ... 2 more items] }.",
"locations": [
{
"line": 9,
"column": 7
}
],
"stacktrace": [
"GraphQLError: Expected value of type \"MovieExtra\" but got: { channel: \"Netflix\", first_air_date: \" First air date Oct. 05, 2018\", last_air_date: \" 脷ltima transmisi贸n Oct. 05, 2018\", total_seasons: \"1\", total_episodes: \"8\", season_list: [[Object], [Object]], cast_members: { creator: [Object], members_list: [Array] }, similar_series: [[Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], [Object], ... 2 more items] }.",
" at invalidReturnTypeError (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:707:10)",
" at completeObjectValue (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:699:13)",
" at completeValue (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:591:12)",
" at completeValue (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:557:21)",
" at completeValueCatchingError (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:495:19)",
" at C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:618:25",
" at Array.forEach (<anonymous>)",
" at forEach (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\iterall\\index.js:83:25)",
" at completeListValue (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:614:24)",
" at completeValue (C:\\Users\\c\\Desktop\\cinemanight-graphql\\node_modules\\graphql\\execution\\execute.js:573:12)"
]
}
}
}
],
"data": null
}
Is __solverType similar to __resolveType?
Try changing your code for __solverType to:
__solverType(obj , context , info){
if(obj.type === 'pelicula') return 'SMovies'
if(obj.type === 'serie') return 'SSeries'
}
See if that works.
_Hello @luna215,_
_Sorry, I made the change from __solverType to __resolveType, it was a syntax error._
_But even so, it shows me the same error made in the previous dialogue._
But something that I noticed
console.log ('obj:', obj)
It doesn't show me anything, it's as if resolver Search didn't do anything.
Search:{
__resolveType(obj , context , info){
console.log('obj: ' , obj)
if(obj.type === 'pelicula') return 'SMovies'
if(obj.type === 'serie') return 'SSeries'
}
},
When using unions, you will have to return a __typename so apollo-server knows which type the result has and which resolver map must be used for resolving further field values of the resolved type.
search query must be something like below
Query: {
search: async (_source, { query }, { dataSources }) => {
const data = dataSources.API.search(query)
if (data.name === 'Series') return {
__typename: 'Series',
...data
}
if (data.name === 'Movies') {
__typename: 'Movies',
...data
}
}
}
Simplest (fewest extra lines of code) solution follows:
const resolvers = {
Search:{
__resolveType(parent) {
return parent.constructor.name
}
},
SMovies:{
...
},
SSeries:{
...
},
MovieExtra:{
...
},
SerieExtra:{
...
},
Query: {
search: async(_source , {query} , { dataSources}) =>{
return dataSources.API.search(query)
.then(doc => {
return doc.content;
})
},
}
};
module.exports = resolvers;
No Need for __typename: or _isTypeOf:
For us somehow only __typename worked, but __resolveType didn't (even when returning a static string; using graphql-tools)
works:
Boq: () => ({
elements: () => [
{
priceEstimate: (): BoqPositionPriceEstimate => ({
min: 2000,
max: 7000,
}),
},
],
}),
// force line items to be always be positions,
// otherwise we randomly might not get any and the test fails
BoqLineItem: () => ({
__typename: 'BoqPosition',
}),
doesn't work
Boq: () => ({
elements: () => [
{
priceEstimate: (): BoqPositionPriceEstimate => ({
min: 2000,
max: 7000,
}),
},
],
}),
// force line items to be always be positions,
// otherwise we randomly might not get any and the test fails
BoqLineItem: () => ({
__resolveType: () => 'BoqPosition',
}),
(we wanted to force one type on an array of union typed elements)
Most helpful comment
When using unions, you will have to return a __typename so apollo-server knows which type the result has and which resolver map must be used for resolving further field values of the resolved type.
search query must be something like below