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

UnexpectedObjectType #148

Closed
yonaskolb opened this issue Jul 11, 2023 · 8 comments
Closed

UnexpectedObjectType #148

yonaskolb opened this issue Jul 11, 2023 · 8 comments
Assignees
Labels
bug Something isn't working

Comments

@yonaskolb
Copy link
Contributor

Hi, this library looks great! I've integrated it into a codebase to replace Apollo, but after running it for the first time I'm getting the error unexpectedObjectType(expected: "Dictionary", received: <null>) on the first query. I do notice that other queries do work, so not sure what the issue is. How do I go about diagnosing this?

within OperationResult.decode<T, TypeLock>(selection: Selection<T, TypeLock>) throws -> DecodedOperationResult<T>

po self.data
▿ AnyCodable(["currentUserquery__1aoajeyzqcdt8": <null>])
  ▿ value : 1 element
    ▿ 0 : 2 elements
      - key : "currentUserquery__1aoajeyzqcdt8"
      - value : <null>

This is the query

query currentUser {
  currentUser {
    id
    firstName
    lastName
    phone
    email
    username
    credential
    npiNumber
    npiTaxonomyCode
    npiTaxonomyDescription
    bio
    isStudent
    role
    createdAt
    updatedAt
    lastLoginAt
    cmeGoalValue
    cmeGoalDate
    totalCmeEarned
    topics {
      ...TopicFragment
    }
    followers {
      ...UserFragment
    }
    following {
      ...UserFragment
    }
    posts {
      ...PostFragment
    }
    links {
      ...UserLinkFragment
    }
    comments {
      ...CommentFragment
    }
    likedPosts {
      ...PostFragment
    }
    bookmarkedPosts {
      ...PostFragment
    }
    avatar {
      ...MediaItemFragment
    }
    workHistory {
      ...WorkExperienceFragment
    }
    educationCredits {
      ...EducationCreditFragment
    }
    notificationTokens {
      ...UserNotificationTokenFragment
    }
    notifications {
      ...NotificationFragment
    }
    outgoingNotifications {
      ...NotificationFragment
    }
    searches {
      ...SearchFragment
    }
    apiTokens {
      ...ApiTokenFragment
    }
    likes {
      ...LikeFragment
    }
    bookmarks {
      ...BookmarkFragment
    }
    streamToken
  }
}

Here's some of the code I'm using. Not sure what you need.

// query using a type defined below
struct CurrentUserQuery: GraphQuery {
    func query(graph: Graph) throws -> AuthenticatedUser {
        try graph.currentUser(selection: AuthenticatedUser.selection)
    }
}

// data type
struct AuthenticatedUser: Equatable {
    var streamToken: String
    var profile: Profile

    static let selection = Selection.User<Self> {
        AuthenticatedUser(
            streamToken: try $0.streamToken(),
            profile: try $0.selection(Profile.selection)
        )
    }
}

// my custom operation types for easy selection and mocking
protocol GraphOperation {
    associatedtype Data
}

protocol GraphQuery: GraphOperation {
    typealias Graph = Fields<Objects.Query>
    func query(graph: Graph) throws -> Data
}

protocol GraphMutation: GraphOperation {
    typealias Graph = Fields<Objects.Mutation>
    func mutation(graph: Graph) throws -> Data
}

extension GraphQuery {
    var selection: Selection<Data, Objects.Query> {
        Selection<Data, Objects.Query> {
            try query(graph: $0)
        }
    }
}

extension GraphMutation {
    var selection: Selection<Data, Objects.Mutation> {
        Selection<Data, Objects.Mutation> {
            try mutation(graph: $0)
        }
    }
}
  • OS: iOS 16.4
@yonaskolb
Copy link
Contributor Author

I did some digging and turns out this is the same problem as in this closed issue #109, with missing data when our graphql server returns errors

@yonaskolb
Copy link
Contributor Author

yonaskolb commented Jul 12, 2023

To be more specific this is the data response, which isn't completely missing:

{"errors":[{"message":"must be logged in","path":["currentUserquery_1d56j88me36s2"]}],"data":{"currentUserquery_1d56j88me36s2":null}}

It might be useful to be able to configure the client to just return errors if they are encountered and to not try and parse the data, as not all GraphQL servers seem to stick to the official contract

@yonaskolb
Copy link
Contributor Author

yonaskolb commented Jul 12, 2023

I've worked around this for now by executing the query manually and then throwing any errors that are found before decoding

- client.query(selection, policy: policy)
+ client.executeQuery(for: selection, policy: policy)
+   .tryMap { result in
+     if let error = result.error {
+       throw error // new line that client.query doesn't do
+     }
+     return try result.decode(selection: selection)
+   }

@maticzav maticzav self-assigned this Jul 12, 2023
@maticzav maticzav added the bug Something isn't working label Jul 12, 2023
@maticzav
Copy link
Owner

I've worked around this for now by executing the query manually and then throwing any errors that are found before decoding

- client.query(selection, policy: policy)
+ client.executeQuery(for: selection, policy: policy)
+   .tryMap { result in
+     if let error = result.error {
+       throw error // new line that client.query doesn't do
+     }
+     return try result.decode(selection: selection)
+   }

@yonaskolb which file is that? I'll prepare a PR and merge this right away 😄

@yonaskolb
Copy link
Contributor Author

@yonaskolb which file is that? I'll prepare a PR and merge this right away 😄

https://github.com/maticzav/swift-graphql/blob/main/Sources/SwiftGraphQLClient/Client/Selection.swift#L90

@maticzav
Copy link
Owner

maticzav commented Jul 12, 2023

As I mentioned in the PR, I made some assumptions before that evidently no longer hold.

This issue has been resolved, but the API isn't as good as I want it to be. Instead of delaying a release, I released an imperfect version that should solve the problem for now, but I want to address the overarching issue better in the next release.

I am leaving this issue open as a reminder and a reference to the PR.


@yonaskolb thank you for opening this!

@yonaskolb
Copy link
Contributor Author

Thank you for the quick fix @maticzav! 🙏

@yonaskolb yonaskolb reopened this Jul 13, 2023
@shaps80
Copy link
Collaborator

shaps80 commented Oct 19, 2023

Sounds like this was resolved in a separate PR so I'm closing for now. Moving forwards I will open a Discussion regarding error handling and scenarios where data may be missing etc.

@shaps80 shaps80 closed this as completed Oct 19, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

3 participants