shurcooL / githubv4

Package githubv4 is a client library for accessing GitHub GraphQL API v4 (https://docs.github.com/en/graphql).
MIT License
1.11k stars 89 forks source link

"can't decode into non-slice invalid" #18

Closed spxtr closed 7 years ago

spxtr commented 7 years ago

Of the two following queries, the first succeeds and the second spits up an error. I spent a while adding debug printfs in graphql/internal/jsonutil but I wasn't able to figure it out. All I know is that the Commits object in the second query causes the problem. Removing that object and replacing it with something else in the PR works fine.

Let me know if you need more info :)

package main

import (
    "context"
    "fmt"
    "github.com/shurcooL/githubql"
    "golang.org/x/oauth2"
    "os"
)

type repoQuery struct {
    Repository struct {
        PullRequests struct {
            Nodes []struct {
                Commits struct {
                    Nodes []struct {
                        URL githubql.URI `graphql:"url"`
                    }
                } `graphql:"commits(last: 1)"`
            }
        } `graphql:"pullRequests(first: 1)"`
    } `graphql:"repository(owner: \"kubernetes\", name: \"test-infra\")"`
}

type searchQuery struct {
    Search struct {
        Nodes []struct {
            PullRequest struct {
                Commits struct {
                    Nodes []struct {
                        URL githubql.URI `graphql:"url"`
                    }
                } `graphql:"commits(last: 1)"`
            } `graphql:"... on PullRequest"`
        }
    } `graphql:"search(type: ISSUE, first: 1, query: \"type:pr repo:kubernetes/test-infra\")"`
}   

func main() {
    src := oauth2.StaticTokenSource(
        &oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")},
    )   
    httpClient := oauth2.NewClient(context.Background(), src)

    client := githubql.NewClient(httpClient)
    sq := searchQuery{}
    if err := client.Query(context.Background(), &sq, nil); err != nil {
        fmt.Printf("Search error: %v\n", err)
    }
    rq := repoQuery{}
    if err := client.Query(context.Background(), &rq, nil); err != nil {
        fmt.Printf("Repo error: %v\n", err)
    }
} 
$ GITHUB_TOKEN=<redacted> go run test.go
Search error: can't decode into non-slice invalid
dmitshur commented 7 years ago

Thanks a lot for reporting this. I suspect this could be a bug in jsonutil on some particular edge case. That's where the error comes from.

Quick question, are you using the latest version of githubql (and its dependencies)? Or something older?

I will try to reproduce it, investigate it, and fix it if it's a bug on my side.

spxtr commented 7 years ago

Thanks for the quick response. I'm using https://github.com/shurcooL/githubql/commit/b3091cd0b2f573f6945eb6f15b0559c06330a1a8 and https://github.com/shurcooL/graphql/commit/52ce28a2c9fdfbdb3377232422c7915fa04b678a.

dmitshur commented 7 years ago

Thanks. I can reproduce with latest. Most likely it's a bug in jsonutil. I'll investigate and post updates.

dmitshur commented 7 years ago

This was indeed a bug in jsonutil. It was not able to handle this query because there was a slice of nodes inside an inline fragment. I missed that edge case in #15. As I wrote there:

This is a large and riskier-than-usual PR. It replaces the extremely well-tested encoding/json unmarshaler with a brand new that was implemented over the last few days for the custom needs of graphql: to unmarshal a JSON-encoded GraphQL server response into a query data structure. So there's a chance of edge cases that are not going to be handled.

That's what happened here.

This is now fixed via https://github.com/shurcooL/graphql/commit/68e5b1b3ab56633e42939506bc61f0b9fb2b7a79. I've also added a test so this won't regress.

You should see the problem go away after updating to the latest version:

go get -u github.com/shurcooL/githubql

(Or equivalent if you're using vendoring.)

The test program you provided no longer prints an error. I modified it slightly to print the query result to stdout as JSON:

Test Program Output ``` $ GITHUB_TOKEN= go run test.go { "Search": { "Nodes": [ { "PullRequest": { "Commits": { "Nodes": [ { "URL": "https://github.com/kubernetes/test-infra/pull/4246/commits/84b959753c879e4253d54a2dda97913b55013571" } ] } } } ] } } { "Repository": { "PullRequests": { "Nodes": [ { "Commits": { "Nodes": [ { "URL": "https://github.com/kubernetes/test-infra/pull/1/commits/b1770aeac94fa947e5883d8b9b38d435582dd93d" } ] } } ] } } } ```

Thank you very much @spxtr for reporting this bug and providing an easily reproducible test case! Let me know if you run into any other issues.