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

unable to bind to interface when updating gqlgen #1424

Closed
miroslavLalev opened this issue Dec 18, 2020 · 4 comments
Closed

unable to bind to interface when updating gqlgen #1424

miroslavLalev opened this issue Dec 18, 2020 · 4 comments

Comments

@miroslavLalev
Copy link

What happened?

Hello, I've been dealing with update from older version (0.7.2) of gqlgen to the newest - 0.13.0. I am having trouble with code generation for our current schemas - it fails with merging type systems failed: unable to bind to interface: ....

Something goes wrong with a schema like this:

type PageInfo {
    hasNextPage: Boolean!
    hasPreviousPage: Boolean!
}

interface Connection {
    pageInfo: PageInfo!
    totalCount: Int!
}

interface Edge {
    cursor: ID!
}

type AssetEdge implements Edge {
    cursor: ID!
    node: Asset!
}

type ChildrenConnection implements Connection {
    edges: [AssetEdge!]
    pageInfo: PageInfo!
    totalCount: Int!
}

This is just a small segment of the whole schema, as it is rather big and spread across multiple files.
I am also providing external models for most of the types in gqlgen.yml file. The implementation looks around the lines of:

<package paging>
type PageInfo struct {
	HasNextPage     bool `json:"hasNextPage"`
	HasPreviousPage bool `json:"hasPreviousPage"`
}

type Edge interface {
	Cursor() string
}

type Connection interface {
	PageInfo() *PageInfo
	TotalCount() int
}
<package assets>
type AssetEdge struct {
	cursor string
	node   models.Asset
}

func (r *AssetEdge) Cursor() string {
	return r.cursor
}

func (r *AssetEdge) Node() models.Asset {
	return r.node
}

type ChildrenConnection struct {
	totalCount int
	pageInfo   *paging.PageInfo
	Edges      []AssetEdge
}

func (r *ChildrenConnection) TotalCount() int {
	return r.totalCount
}

func (r *ChildrenConnection) PageInfo() *paging.PageInfo {
	return r.pageInfo
}

As you can see, ChildrenConnection implements the Connection interface, and everything generates properly with versions less than 0.11.0. However, if I try generating with anything above that, I get the following error:

merging type systems failed: unable to bind to interface: <package assets>.ChildrenConnection does not satisfy the interface <package paging>.Connection

I've tried to debug why the generator thinks that interfaces are not satisfied and it has something to do with the PageInfo method - for some reason it thinks that the signatures are not the same. More interestingly, if I remove that method (and the attribute from the schema), everything starts generating successfully again. I've tried to switch the return type to just PageInfo, instead of *PageInfo but that did not work as well.

I've also checked that the following PR introduces checks for interfaces satisfaction, so I believe it is where my problems originate from.

What did you expect?

Properly generated go files.

Minimal graphql.schema and models to reproduce

Sadly, I could not reproduce the results when trying to create a new project with only the specified schema here. I would suspect that the remaining parts might also take part in the behaviour that I am describing, just don't know how - we have multiple implementers of the Connection interface.

versions

  • gqlgen version? 0.13.0
  • go version? 1.15.6
  • dep or go modules? go modules
@tankbusta
Copy link

tankbusta commented Jan 26, 2021

Hey @miroslavLalev I just ran into this and figured I'd share a workaround. I run into this as I have 3 different "File" schemas that all implement at least the BaseFile interface.

interface BaseFile {
    md5: String!
    sha1: String!
    sha256: String!
    filename: String!
    size: Int!
}

type File implements BaseFile @goModel(model: "redacted/server/storage.File") {
    id: ID!
    md5: String!
    sha1: String!
    sha256: String!
    filename: String!
    size: Int!

    ... additional fields removed for brevity
}

I noticed it created a generated interface in my models/models_gen.go that contains

type BaseFile interface {
	IsBaseFile()
}

I went ahead and slapped an empty method on my storage.File structure and I got past the error you're seeing.

merging type systems failed: unable to bind to interface: redacted/server/storage.File does not satisfy the interface redacted/lib/graph/model.BaseFile
exit status 1

@jmhwang7
Copy link

@miroslavLalev we ran into the same issue. There's an open PR here by my colleague which fixes it for our codebase.

@miroslavLalev
Copy link
Author

Hey @jmhwang7, thanks for the heads up! Actually, we decided to look back at our schema and completely dropped the interface, which simplified stuff, and the issue was resolved out of the box.

I will be looking at the PR and resolve this issue after it gets merged.

@ipfans
Copy link
Contributor

ipfans commented Jan 15, 2022

Please notes that this issue have two commits related(#1491, #1763), and should be consider as closed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants