hasura/graphql-engine · error

%s: decoding graphql response errors: %w

Error message

%s: decoding graphql response errors: %w

What it means

This error is raised inside GetIntrospectionSchema when the GraphQL response contains a non-empty 'errors' array but the CLI fails to unmarshal that errors payload (respBody.Errors.UnmarshalJSON) into structured GraphQL error objects. In other words, the server returned errors in a shape the client's error type does not understand, so even the error content is lost and only the decoding failure is reported. Unlike sibling errors, it is not tagged KindHasuraAPI but wrapped generically with the operation name.

Source

Thrown at cli/internal/hasura/v1graphql/v1graphql.go:65

	}

	if err != nil {
		return nil, errors.E(op, err)
	}

	err = json.NewDecoder(responseBody).Decode(&respBody)
	if err != nil {
		return nil, errors.E(op, err)
	}

	if respBody.Errors != nil {
		var b []byte

		err := respBody.Errors.UnmarshalJSON(b)
		if err != nil {
			return nil, errors.E(
				op,
				fmt.Errorf("%s: decoding graphql response errors: %w", opName, err),
			)
		}

		return nil, errors.E(op, fmt.Errorf("%s: %w", opName, err))
	}

	var schema hasura.IntrospectionSchema
	if respBody.Data != nil {
		err = json.Unmarshal(*respBody.Data, &schema)
		if err != nil {
			return nil, errors.E(
				op,
				fmt.Errorf("%s: decoding graphql responnse data: %w", opName, err),
			)
		}
	}

	return schema, nil

View on GitHub (pinned to 724551b9ae)

Solutions

  1. Capture the raw response body (run CLI with --debug or reproduce the introspection query with curl) to see the actual 'errors' structure
  2. If a proxy/middleware rewrites GraphQL errors, bypass it or fix it to pass the standard errors array through
  3. Update the CLI to a version whose error unmarshalling matches your server's response format
  4. If the server is not standard Hasura v1graphql, point the introspection flow at a compatible endpoint

Example fix

// before
schema, err := c.GetIntrospectionSchema()
if err != nil { return err }

// after
schema, err := c.GetIntrospectionSchema()
if err != nil {
  if strings.Contains(err.Error(), "decoding graphql response errors") {
    // non-standard errors payload: inspect raw body via --debug / curl
    return fmt.Errorf("non-standard GraphQL error payload from server: %w", err)
  }
  return err
}
Defensive patterns

Strategy: type-guard

Validate before calling

// Reproduce the introspection query with curl and validate the errors field shape:
// curl -s -H "X-Hasura-Admin-Secret: $SECRET" -d '{"query":"IntrospectionQuery"}' ENDPOINT/v1/graphql | jq 'type, .errors|type'

Type guard

func isGraphqlErrorDecodeError(err error) bool {
  return err != nil && strings.Contains(err.Error(), "decoding graphql response errors")
}

Try / catch

schema, err := c.GetIntrospectionSchema()
if err != nil {
  if isGraphqlErrorDecodeError(err) {
    // server sent a non-standard errors payload; capture raw body and inspect
    return inspectRawResponse(err)
  }
  return err
}

Prevention

When it happens

Trigger: A v1/graphql response whose 'errors' field is not the expected array of {message, extensions} objects — e.g. a plain string, a nested object, null sub-fields, or a non-JSON body that still parsed as a GraphQL envelope — causing json.Unmarshal inside the custom Errors type to fail.

Common situations: Non-Hasura GraphQL gateways or proxies that emit non-standard error shapes, older/newer Hasura versions with changed error formats, or custom response middleware on the server altering the errors field before the CLI sees it.

Related errors


AI-assisted analysis of hasura/graphql-engine@724551b9ae (2026-08-28). Data as JSON: /api/errors/d28b17a9a6713892. Report an issue: GitHub.