nats-io/nats-server · error

auth callout service returned an error: %v

Error message

auth callout service returned an error: %v

What it means

The auth callout response JWT itself contained a non-empty Error field, meaning the callout service explicitly refused or failed the authorization request. The server surfaces that error text verbatim to the connecting client's auth flow. This is the designed mechanism for a callout to deny a connection with a reason.

Source

Thrown at server/auth_callout.go:137

		vr := jwt.CreateValidationResults()
		cr.Validate(vr)
		if len(vr.Issues) > 0 {
			return nil, fmt.Errorf("authorization response had validation errors: %v", vr.Issues[0])
		}

		// the subject is the user id
		if cr.Subject != pub {
			return nil, errors.New("auth callout violation: auth callout response is not for expected user")
		}

		// check the audience to be the server ID
		if cr.Audience != s.info.ID {
			return nil, errors.New("auth callout violation: auth callout response is not for server")
		}

		// check if had an error message from the auth account
		if cr.Error != _EMPTY_ {
			return nil, fmt.Errorf("auth callout service returned an error: %v", cr.Error)
		}

		// if response is encrypted none of this is needed
		if isOperatorMode && !encrypted {
			pkStr := cr.Issuer
			if cr.IssuerAccount != _EMPTY_ {
				pkStr = cr.IssuerAccount
			}
			if pkStr != account {
				if _, ok := acc.hasIssuer(pkStr); !ok {
					return nil, errors.New("auth callout signing key is unknown")
				}
			}
		}

		return jwt.DecodeUserClaims(cr.Jwt)
	}

View on GitHub (pinned to 3a66a489d2)

Solutions

  1. Read the %v message — it is the callout service's own denial reason — and fix credentials/permissions on the client or rules in the callout service.
  2. Check the auth callout service's logs to see why it set cr.Error.
  3. Verify the external identity backend the callout consults is healthy.
  4. If the denial is wrong, update the callout service's authorization logic or account mapping.
Defensive patterns

Strategy: try-catch

Try / catch

if err != nil && strings.Contains(err.Error(), "auth callout service returned an error") {
    // denial reason follows ': ' — surface it to the operator/client
    log.Printf("callout denied connection: %s", err)
}

Prevention

When it happens

Trigger: The callout service publishes an AuthorizationResponseClaims with cr.Error set to a non-empty message (e.g. "user not found", "account suspended") in reply to an authorization request.

Common situations: User credentials rejected by the external auth backend; upstream identity provider outage causing the callout to report an error; misconfigured callout rules denying valid users.

Related errors


AI-assisted analysis of nats-io/nats-server@3a66a489d2 (2026-09-02). Data as JSON: /api/errors/9eb82f4396e4bf7d. Report an issue: GitHub.