Search code examples
expressgraphqlapolloapollo-server

Return custom Error in Union Graphql Type while show list data | returning list with union type in graphql


I'm using Apollo server for my project returning list(array) of data when I try to return Error union type it shows this error:

  "errors": [
    {
      "message": "Expected Iterable, but did not find one for field \"Query.getReports\".",

My Schema:

type Query {
    getReports(id: ID!, patient_id: Int): [getReportUnion]!
  }

  union getReportUnion = Error | getReportResult 

  type getReportResult {
    id: ID!
    patient_id: Int!
  }

  type Error {
    error: Boolean!
    message: String!
  }

my Resolver:

  getReports: async (parent: any, args: any, context: any, info: any) => {
    /**
     * Simplify
     */
    const { id, patient_id } = args;
    const { isAuth, userId } = context.Auth;
    
    /**
     * Authenticating user is logged in
     */
    if (!!!isAuth || userId !== id)
      return { __typename: "Error", error: err, message: mesg };

   // if a user is logged in then it works well
  }

and my query:

query {
  getReports(id: "5f449b73e2ccbc43aa5204d88", patient_id: 0) {
  __typename
    ... on getReportResult {
            patient_id
      date
    }
    ... on Error {
      error
      message
    }
  }
}

The problem is when I tried to pass the wrong id argument or jwt token, it shows the error. if every id and jwt token as header are right then it works like charm. so question is when id or jwt token is wrong, I want to show the Error type to inform user something isn't alright!

I already tried but not working:

 type Query {
        getReports(id: ID!, patient_id: Int): getReportUnion!
      }
    
      union getReportUnion = Error | [getReportResult] 

it shows another error, is there any workaround to get rid of this error and show the Error. your answer is valuable to us!


Solution

  • If your field's type is a List, then your resolver must return either an iterable (i.e. an array) or a Promise that resolves to one.

    The type for your field is a List ([getReportUnion]). However, inside your resolver, you are returning an object literal:

    return { __typename: "Error", error: err, message: mesg }
    

    You should return an array instead:

    return [{ __typename: "Error", error: err, message: mesg }]
    

    There is no way for you to return either a List of getReportResult objects or a single Error object. The only way to do that would be to wrap getReportResult with another type and use that type inside your union instead.

    type Query {
        getReports(id: ID!, patient_id: Int): GetReportPayload!
      }
    
      union GetReportPayload = Error | GetReportResults
    
      type GetReportResults {
        results: [Report!]!
      }
    
      type Report {
        id: ID!
        patientId: Int!
      }
    
      type Error {
        error: Boolean!
        message: String!
      }