{"record":{"id":"17bdbf16c5605bde","repo":"dgraph-io/dgraph","slug":"unexpected-error-with-v","errorCode":null,"errorMessage":"unexpected error with: %v","messagePattern":"unexpected error with: (.+?)","errorType":"http","errorClass":null,"httpStatus":null,"severity":"error","filePath":"graphql/schema/custom_http.go","lineNumber":121,"sourceCode":"\n\t\t// find out the data returned for the GraphQL query\n\t\tvar ok bool\n\t\tif response, ok = graphqlResp.Data[fconf.RemoteGqlQueryName]; !ok {\n\t\t\treturn nil, nil, append(softErrs, keyNotFoundError(field, fconf.RemoteGqlQueryName))\n\t\t}\n\t} else {\n\t\t// this was a REST request\n\t\tif resp.StatusCode >= 200 && resp.StatusCode < 300 {\n\t\t\t// if this was a successful request, lets try to unmarshal the response\n\t\t\tif err = Unmarshal(b, &response); err != nil {\n\t\t\t\treturn nil, nil, x.GqlErrorList{jsonUnmarshalError(err, field)}\n\n\t\t\t}\n\t\t} else {\n\t\t\t// if we get unsuccessful response from the REST api, lets try to see if\n\t\t\t// it sent any errors in the form expected for GraphQL errors.\n\t\t\tif err = Unmarshal(b, &graphqlResp); err != nil {\n\t\t\t\terr = fmt.Errorf(\"unexpected error with: %v\", resp.StatusCode)\n\t\t\t\treturn nil, nil, x.GqlErrorList{externalRequestError(err, field)}\n\t\t\t} else {\n\t\t\t\treturn nil, nil, graphqlResp.Errors\n\t\t\t}\n\t\t}\n\t}\n\n\treturn response, softErrs, nil\n}\n\nfunc keyNotFoundError(f Field, key string) *x.GqlError {\n\treturn f.GqlErrorf(nil, \"Evaluation of custom field failed because key: %s \"+\n\t\t\"could not be found in the JSON response returned by external request \"+\n\t\t\"for field: %s within type: %s.\", key, f.Name(), f.GetObjectName())\n}\n\nfunc jsonMarshalError(err error, f Field, input interface{}) *x.GqlError {\n\treturn f.GqlErrorf(nil, \"Evaluation of custom field failed because json marshaling \"+","sourceCodeStart":103,"sourceCodeEnd":139,"githubUrl":"https://github.com/dgraph-io/dgraph/blob/759e242be62c91f8d084da06ad0c8d21256d9c07/graphql/schema/custom_http.go#L103-L139","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","solutions":["Check the remote endpoint's logs for why it returned a non-2xx status","Make the remote endpoint return GraphQL-style errors: {\"errors\":[{\"message\":\"...\"}]}","Verify the URL, headers and auth in the @custom directive are correct","Add retry/backoff on the remote service for transient failures"],"exampleFix":"// remote endpoint returning:\n<html>502 Bad Gateway</html>\n// should return:\n{\"errors\":[{\"message\":\"upstream unavailable\"}]}","handlingStrategy":"retry","validationCode":"// pre-flight: confirm remote returns GraphQL-shaped errors\nconst res = await fetch(url, {method:'POST', headers, body})\nconst ct = res.headers.get('content-type')\nif (!res.ok && !(ct||'').includes('application/json')) throw new Error('remote returns non-JSON errors')","typeGuard":"func hasGraphqlErrorShape(body []byte) bool {\n  var r struct{ Errors []json.RawMessage `json:\"errors\"` }\n  return json.Unmarshal(body, &r) == nil && r.Errors != nil\n}","tryCatchPattern":"result := resolver(ctx, field)\nfor _, e := range result.Errors {\n  if strings.Contains(e.Message, \"unexpected error with: \") {\n    // remote failed with non-GraphQL body; inspect status code in message, retry with backoff\n  }\n}","preventionTips":["Monitor remote endpoint health and status codes","Ensure remote returns {errors:[{message}]} on failure","Configure timeouts and retries on the remote service","Keep URL/headers/auth in the @custom directive current"],"tags":["graphql","custom-resolver","remote","http","dgraph"],"backgroundTag":"remote-resolver-http-error","analyzedSha":"759e242be62c91f8d084da06ad0c8d21256d9c07","analyzedAt":"2026-09-01T14:42:12.034Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}