Type mismatch between variable and argument for optional String / ID
andyfeller opened this issue ยท 12 comments
In trying to query the GitHub repositoryOwner
for retrieving repositories for organizations and/or users, I ran into a problem involving the workaround from #12 as the interface does not appear to like ID
for EndCursor
.
When calling this query, the following error is returned from GitHub GraphQL API:
Error: Message: Type mismatch on variable $endCursor and argument after (ID / String), Locations: [{Line:1 Column:101}]
type reposQuery struct {
RepositoryOwner struct {
Repositories struct {
Nodes []struct {
Name string
}
PageInfo struct {
HasNextPage bool
EndCursor string
}
} `graphql:"repositories(first: 100, after: $endCursor, ownerAffiliations: [OWNER])"`
} `graphql:"repositoryOwner(login: $owner)"`
}
func getRepos(owner string, endCursor *string) (*reposQuery, error) {
query := new(reposQuery)
variables := map[string]interface{}{
"owner": graphql.String(owner),
"endCursor": endCursor,
}
err := client.Query("getRepos", query, variables)
return query, err
}
In stepping through the code, the error emerges in decoding the response from the server where the query
is generated as:
"query getRepos($endCursor:ID$owner:String!){repositoryOwner(login: $owner){repositories(first: 100, after: $endCursor, ownerAffiliations: [OWNER]){nodes{name},pageInfo{hasNextPage,endCursor}}}}"
Any assistance would be greatly appreciated ๐
For reference, this query works with the interface mentioned:
query($owner: String!, $endCursor: String) {
repositoryOwner(login: $owner) {
repositories(first: 100, ownerAffiliations: [OWNER], after: $endCursor) {
pageInfo {
hasNextPage
endCursor
}
nodes {
name
nameWithOwner
}
}
}
}
If you look at GitHub's RepositoryOwner
interface, the after
argument of the repositories
field has type String
, so that's what needs to be provided. Your code can look something like:
variables := map[string]interface{}{
"owner": githubv4.String(owner),
"endCursor": githubv4.String(endCursor),
}
See here for an example of similar code.
Thanks for the follow up, @dmitshur ! That is what I initially did, however because the endpoint wants endCursor
to be optional, I had to change it to a pointer. Does that make sense?
Yes, if it's an optional GraphQL type, using a Go pointer makes sense. That is also what's done in the code example I linked above. The NewString
helper exists for convenience of doing this.
So, this is where we're coming full circle as when I'm providing the pointer, GitHub is responding back with the following error:
Error: Message: Type mismatch on variable $endCursor and argument after (ID / String), Locations: [{Line:1 Column:101}]
with the underlying generated query being:
"query getRepos($endCursor:ID$owner:String!){repositoryOwner(login: $owner){repositories(first: 100, after: $endCursor, ownerAffiliations: [OWNER]){nodes{name},pageInfo{hasNextPage,endCursor}}}}"
The only thing I can guess is that the repositoryOwner
interface does not like $endCursor:ID
with however the variable is being sent over.
From what you've shared, I'm fairly confident the problem is with the variables
map you're providing to the Query
call, specifically this code:
query := new(reposQuery)
variables := map[string]interface{}{
"owner": graphql.String(owner),
"endCursor": endCursor,
}
err := client.Query("getRepos", query, variables)
I think changing it to the following should work:
query := new(reposQuery)
variables := map[string]interface{}{
"owner": graphql.String(owner),
"endCursor": graphql.NewString(graphql.String(endCursor)),
}
err := client.Query("getRepos", query, variables)
If that doesn't help, can you post a complete program that reproduces the issue for you?
Finally, take a look at https://github.com/shurcooL/githubv4#pagination if you haven't already, since that is a functional example for pagination.
I'll give it a go! (pun not intended) Seriously: thank you for your amazing patience and help โค๏ธ
"endCursor": graphql.NewString(graphql.String(endCursor)),
Unfortunately, this doesn't really solve it especially as it gives compiler errors:
cannot convert endCursor (variable of type *string) to graphql.String compiler InvalidConversion
I've made my repo public and the code is here: https://github.com/andyfeller/gh-dependency-report/blob/initial/cmd/root.go#L294
I'm simply trying to run this as:
go run main.go andyfeller
Ah, that snippet assumed that endCursor
was of type string
, but in your code its type is *string
. In that case, you can just convert it to a *graphql.String
directly:
func getRepos(owner string, endCursor *string) (*reposQuery, error) {
query := new(reposQuery)
variables := map[string]interface{}{
"owner": graphql.String(owner),
"endCursor": (*graphql.String)(endCursor),
}
err := client.Query("getRepos", query, variables)
return query, err
}
With that change, the program compiles and getRepos
makes a successful query with repository names populated. (There are other parts of that program that need modification to run without errors, for example repos = make([]string, 100)
creates a slice with 100 empty repository names; it should probably be repos = make([]string, 0, 100)
to create an empty slice with 100 capacity.)
Thank you again for your patience, @dmitshur ๐
Would you welcome a PR including a section providing an example of this to avoid confusion from other users?
With that change, the program compiles and
getRepos
makes a successful query with repository names populated. (There are other parts of that program that need modification to run without errors, for examplerepos = make([]string, 100)
creates a slice with 100 empty repository names; it should probably berepos = make([]string, 0, 100)
to create an empty slice with 100 capacity.)
๐ thanks for the additional advice; it's been a while since my undergraduate days of only doing C development and this is the 3rd time I've tried teaching myself GoLang.
Would you welcome a PR including a section providing an example of this to avoid confusion from other users?
I believe this should be covered by https://github.com/shurcooL/githubv4#pagination; can you please let me know if you think something is missing from there?
I'll close this since I understand the question is resolved.