dgraph-io/dgraph · error

expecting either JWKUrl or JWKUrls, both were given

Error message

expecting either JWKUrl or JWKUrls, both were given

What it means

The `validate` method of Dgraph's Authorization configuration (AuthMeta, from the @auth directive's Dgraph.Authorization header) rejects configs that set both `JWKUrl` (single URL) and `JWKUrls` (list of URLs). Only one mechanism for supplying JSON Web Key sets is allowed.

Source

Thrown at graphql/authorization/auth.go:74

	Namespace       string
	Algo            string
	SigningMethod   jwt.SigningMethod `json:"-"` // Ignoring this field
	Audience        []string
	httpClient      *http.Client
	ClosedByDefault bool
}

// Validate required fields.
func (a *AuthMeta) validate() error {
	var fields string

	// If JWKUrl/JWKUrls is provided, we don't expect (VerificationKey, Algo),
	// they are needed only if JWKUrl/JWKUrls is not present there.
	if len(a.JWKUrls) != 0 || a.JWKUrl != "" {

		// User cannot provide both JWKUrl and JWKUrls.
		if len(a.JWKUrls) != 0 && a.JWKUrl != "" {
			return fmt.Errorf("expecting either JWKUrl or JWKUrls, both were given")
		}

		if a.VerificationKey != "" || a.Algo != "" {
			return fmt.Errorf("expecting either JWKUrl/JWKUrls or (VerificationKey, Algo), both were given")
		}

		// Audience should be a required field if JWKUrl is provided.
		if len(a.Audience) == 0 {
			fields = " `Audience` "
		}
	} else {
		if a.VerificationKey == "" {
			fields = " `Verification key`/`JWKUrl`/`JWKUrls`"
		}

		if a.Algo == "" {
			fields += " `Algo`"
		}

View on GitHub (pinned to 759e242be6)

Solutions

  1. Remove `JWKUrl` and keep only the `JWKUrls` array (preferred for multiple key sets)
  2. Or remove `JWKUrls` and keep only `JWKUrl` if you have exactly one JWKS endpoint
  3. Restart Dgraph after fixing the Dgraph.Authorization header value

Example fix

// before
Dgraph.Authorization: {"JWKUrl":"https://idp/.well-known/jwks.json","JWKUrls":["https://idp/.well-known/jwks.json"],"Namespace":"https://dgraph.io/jwt/claims","Audience":["dgraph"],"Algo":"RS256"}
// after
Dgraph.Authorization: {"JWKUrls":["https://idp/.well-known/jwks.json"],"Namespace":"https://dgraph.io/jwt/claims","Audience":["dgraph"],"Algo":"RS256"}
Defensive patterns

Strategy: validation

Validate before calling

const auth = JSON.parse(process.env.DGRAPH_AUTHORIZATION);
if (auth.JWKUrl && Array.isArray(auth.JWKUrls) && auth.JWKUrls.length) {
  throw new Error('Set either JWKUrl or JWKUrls, not both');
}

Type guard

const usesSingleJwk = (a) => typeof a.JWKUrl === 'string' && a.JWKUrl !== '' && !(a.JWKUrls?.length);
const usesMultipleJwks = (a) => Array.isArray(a.JWKUrls) && a.JWKUrls.length > 0 && !a.JWKUrl;

Prevention

When it happens

Trigger: Setting the Dgraph.Authorization header so that its JSON contains a non-empty JWKUrls array AND a non-empty JWKUrl string at the same time, then calling Parse (typically at server start-up when the authorization header is parsed).

Common situations: Migrating a config from the old single JWKUrl field to the newer JWKUrls list and leaving the old key in place; copying a sample config that already had JWKUrl and adding JWKUrls without removing it; merging multiple auth config fragments.

Related errors


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