99designs / 99designs/gqlgen

Element is null, which is not allowed error when errors are added to context only

未关闭
#3,510 1 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看
主要语言
Go
星标
10.8k
派生
1.3k
平均合并
2 天 36 分钟
30 天内合并 PR
26

描述

I'm getting error `the requested element is null which the schema does not allow` when adding errors to the GraphQL context and `return nil, nil` from resolver.

I have this query defined and resolver below. If I'm returning `nil, err` it is fine. I see proper GraphQL error response. Meaning `{"data": null, "errors": ...}`.

But in second case, I can get mutli error from `payload.BuildURL`. Based on error type inside I can differentiate which input was wrong.
However, that fails with `the requested element is null which the schema does not allow`. And to me that is strange.

I understand, that in schema I have non-nullable response. And if I would see that error in both cases (returning error directly and adding to context) it would be fine. But this is strange.

```graphql
query {
externalDataResolverReplacePlaceholders(
config: ExternalDataResolverConfigInput!
values: Map
): ExternalDataResolverReplacedPlaceholders!
}
```

Resolver:

```go
func ErrorOnPath(ctx context.Context, err error, path ...string) error {
gqlErr = gqlerror.WrapPath(graphql.GetPath(ctx), err)
for _, v := range path {
gqlErr.Path = append(gqlErr.Path, ast.PathName(v))
}
return gqlErr
}

func (*queryResolver) ExternalDataResolverReplacePlaceholders(
ctx context.Context,
cfg model.ExternalDataResolverConfigInput,
values map[string]any,
) (*model.ExternalDataResolverReplacedPlaceholders, error) {
if uri, err := url.Parse(cfg.URL); err != nil || !uri.IsAbs() {
// Here I return nil as response together with error and it is fine
return nil, ErrorOnPath(ctx, errors.New("URL must be valid and absolute"), "config", "URL")
}

resp := &model.ExternalDataResolverReplacedPlaceholders{}
var err error

resp.URL, err = payload.BuildURL(cfg.URL, values)
if err != nil {
if me, ok := err.(*payload.MultiError); ok {
for _, e := range me.Errors {
switch e := e.(type) {
case *payload.MissingVariableError:
graphql.AddError(ctx, ErrorOnPath(ctx, e, "values"))
case *payload.InvalidDefaultValueError:
graphql.AddError(ctx, ErrorOnPath(ctx, e, "config", "URL"))
}
}
// Here if I return nil, and all errors are added to context, this is an issue
return nil, nil
}

return nil, ErrorOnPath(ctx, err, "config", "URL")
}
return resp, nil
}
```

---

I was debugging that deeper into generated code, and I spot 1 place which causes the trouble I believe. But not sure if fixing that wouldn't break the rest of the code.

When I was debugging, I got here in generated code:

```go
if v == nil {
if !graphql.HasFieldError(ctx, graphql.GetFieldContext(ctx)) {
ec.Errorf(ctx, "the requested element is null which the schema does not allow")
}
return graphql.Null
}
```

`v` in my case is `nil` so it is checking if field has error with this code. But when it goes to `equalPath`, input parameters are follow:

- `path` contains `["externalDataResolverReplacePlaceholders"]`
- `err.Path` contains `["externalDataResolverReplacePlaceholders", "values"]`

so `equalPath` returns false, which means that HasFieldError is false too and then I see the `"the requested element is null..."` error.

```go
func HasFieldError(ctx context.Context, rctx *FieldContext) bool {
...
for _, err := range c.errors {
if equalPath(err.Path, path) {
return true
}
}
...
}
```

贡献指南

打开贡献指南

评估

这个 Issue 还没有评估数据。

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。