dgraph-io/dgraph · error

unexpected error with: %v

Error message

unexpected error with: %v

What it means

When a custom (remote) GraphQL/REST resolver receives a non-2xx HTTP response, Dgraph tries to unmarshal the body as GraphQL-format errors (Unmarshal into graphqlResp). If that unmarshal also fails, it wraps the failure as "unexpected error with: <status code>" and returns a GqlError referencing the field. It means the remote endpoint failed AND did not return errors in the expected GraphQL error shape.

Source

Thrown at graphql/schema/custom_http.go:121

		// find out the data returned for the GraphQL query
		var ok bool
		if response, ok = graphqlResp.Data[fconf.RemoteGqlQueryName]; !ok {
			return nil, nil, append(softErrs, keyNotFoundError(field, fconf.RemoteGqlQueryName))
		}
	} else {
		// this was a REST request
		if resp.StatusCode >= 200 && resp.StatusCode < 300 {
			// if this was a successful request, lets try to unmarshal the response
			if err = Unmarshal(b, &response); err != nil {
				return nil, nil, x.GqlErrorList{jsonUnmarshalError(err, field)}

			}
		} else {
			// if we get unsuccessful response from the REST api, lets try to see if
			// it sent any errors in the form expected for GraphQL errors.
			if err = Unmarshal(b, &graphqlResp); err != nil {
				err = fmt.Errorf("unexpected error with: %v", resp.StatusCode)
				return nil, nil, x.GqlErrorList{externalRequestError(err, field)}
			} else {
				return nil, nil, graphqlResp.Errors
			}
		}
	}

	return response, softErrs, nil
}

func keyNotFoundError(f Field, key string) *x.GqlError {
	return f.GqlErrorf(nil, "Evaluation of custom field failed because key: %s "+
		"could not be found in the JSON response returned by external request "+
		"for field: %s within type: %s.", key, f.Name(), f.GetObjectName())
}

func jsonMarshalError(err error, f Field, input interface{}) *x.GqlError {
	return f.GqlErrorf(nil, "Evaluation of custom field failed because json marshaling "+

View on GitHub (pinned to 759e242be6)

Solutions

  1. Check the remote endpoint's logs for why it returned a non-2xx status
  2. Make the remote endpoint return GraphQL-style errors: {"errors":[{"message":"..."}]}
  3. Verify the URL, headers and auth in the @custom directive are correct
  4. Add retry/backoff on the remote service for transient failures

Example fix

// remote endpoint returning:
<html>502 Bad Gateway</html>
// should return:
{"errors":[{"message":"upstream unavailable"}]}
Defensive patterns

Strategy: retry

Validate before calling

// pre-flight: confirm remote returns GraphQL-shaped errors
const res = await fetch(url, {method:'POST', headers, body})
const ct = res.headers.get('content-type')
if (!res.ok && !(ct||'').includes('application/json')) throw new Error('remote returns non-JSON errors')

Type guard

func hasGraphqlErrorShape(body []byte) bool {
  var r struct{ Errors []json.RawMessage `json:"errors"` }
  return json.Unmarshal(body, &r) == nil && r.Errors != nil
}

Try / catch

result := resolver(ctx, field)
for _, e := range result.Errors {
  if strings.Contains(e.Message, "unexpected error with: ") {
    // remote failed with non-GraphQL body; inspect status code in message, retry with backoff
  }
}

Prevention

When it happens

Trigger: A @custom GraphQL resolver's remote URL returns a non-200 status (4xx/5xx) with a body that is not the expected {errors:[...]} JSON — e.g. an HTML error page, empty body, plain text, or REST-style JSON error.

Common situations: Remote endpoint behind a proxy returning 502 HTML pages; auth failures returning non-GraphQL JSON; rate-limit responses; the remote server being a REST API that doesn't follow the GraphQL error spec.

Related errors


AI-assisted analysis of dgraph-io/dgraph@759e242be6 (2026-09-01). Data as JSON: /api/errors/17bdbf16c5605bde. Report an issue: GitHub.