{"record":{"id":"31cb2a6aecf937de","repo":"nats-io/nats-server","slug":"user-jwt-is-not-valid-v","errorCode":null,"errorMessage":"user JWT is not valid: %v","messagePattern":"user JWT is not valid: (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"server/auth_callout.go","lineNumber":237,"sourceCode":"\t\t\t// only allow placement if we are not in operator mode\n\t\t\tplacement = arc.Audience\n\t\t} else {\n\t\t\tplacement = issuerAccount\n\t\t}\n\n\t\ttargetAcc, err := s.LookupAccount(placement)\n\t\tif err != nil {\n\t\t\treturn nil, fmt.Errorf(\"no valid account %q for auth callout response on account %q: %v\", placement, account, err)\n\t\t}\n\t\tif isOperatorMode {\n\t\t\t// this will validate the signing key that emitted the user, and if it is a signing\n\t\t\t// key it assigns the permissions from the target account\n\t\t\tif scope, ok := targetAcc.hasIssuer(arc.Issuer); !ok {\n\t\t\t\treturn nil, fmt.Errorf(\"user JWT issuer %q is not known\", arc.Issuer)\n\t\t\t} else if scope != nil {\n\t\t\t\t// this possibly has to be different because it could just be a plain issued by a non-scoped signing key\n\t\t\t\tif err := scope.ValidateScopedSigner(arc); err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"user JWT is not valid: %v\", err)\n\t\t\t\t} else if uSc, ok := scope.(*jwt.UserScope); !ok {\n\t\t\t\t\treturn nil, fmt.Errorf(\"user JWT is not a valid scoped user\")\n\t\t\t\t} else if arc.User.UserPermissionLimits, err = processUserPermissionsTemplate(uSc.Template, arc, targetAcc); err != nil {\n\t\t\t\t\treturn nil, fmt.Errorf(\"user JWT generated invalid permissions: %v\", err)\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn targetAcc, nil\n\t}\n\n\tprocessReply := func(_ *subscription, rc *client, racc *Account, subject, reply string, rmsg []byte) {\n\t\tarc, err := decodeResponse(rc, rmsg, racc)\n\t\tif err != nil {\n\t\t\tc.authViolation()\n\t\t\trespCh <- titleCase(err.Error())\n\t\t\treturn\n\t\t}\n\t\t// If the caller had established that the user should go through a proxy,","sourceCodeStart":219,"sourceCodeEnd":255,"githubUrl":"https://github.com/nats-io/nats-server/blob/3a66a489d262bf89b71a71c955c94920394532f3/server/auth_callout.go#L219-L255","documentation":"The user JWT's issuer was a known scoped signing key on the target account, but scope.ValidateScopedSigner(arc) failed: the claims do not satisfy the restrictions of that signing key's scope (e.g. disallowed permission templates, bearer token constraints, or other scoped-signer rules violated). The server rejects the user JWT as invalid.","triggerScenarios":"Operator-mode callout signs a user JWT with a scoped signing key whose UserScope requirements are not met by the emitted claims — ValidateScopedSigner returns a non-nil err which is wrapped here.","commonSituations":"Callout building permissions that violate the scope's template (e.g. adding pub/sub subjects outside the scoped template); using a scoped key while emitting claims incompatible with scope limits after an nsc/scopes change.","solutions":["Read the wrapped %v detail from ValidateScopedSigner and align the user claims with the scope's restrictions.","Regenerate the signing key scope with nsc so the callout's emitted permissions fit the template.","Sign with a non-scoped account signing key if the callout needs unrestricted claim shapes (and the account JWT permits it).","Update the callout's claim construction to honor the UserScope template (see processUserPermissionsTemplate usage)."],"exampleFix":"// before\narc.User.UserPermissionLimits.Pub.Allow = []string{\"{\">\", \"all-subjects\"} // outside scope template\n// after\narc.User.UserPermissionLimits.Pub.Allow = []string{\"service.subjects.only\"} // within the scoped signer template","handlingStrategy":"validation","validationCode":"scope, ok := targetAccScopes[arc.Issuer]\nif ok {\n    if err := scope.ValidateScopedSigner(arc); err != nil {\n        return fmt.Errorf(\"claims violate scoped signer: %v\", err)\n    }\n}","typeGuard":null,"tryCatchPattern":"if err != nil && strings.Contains(err.Error(), \"user JWT is not valid\") {\n    // read the wrapped ValidateScopedSigner detail and fix claim shape\n}","preventionTips":["Mirror the UserScope template's permission shape when building claims in the callout.","Run ValidateScopedSigner in the callout before publishing the response.","Regenerate scopes and callout claim logic together when scopes change."],"tags":["auth-callout","jwt","scoped-signer"],"backgroundTag":"jwt-scoped-signer-invalid","analyzedSha":"3a66a489d262bf89b71a71c955c94920394532f3","analyzedAt":"2026-09-02T04:41:54.247Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T15:18:49.778Z"}