{"record":{"id":"da37b95b0c7abf6c","repo":"hyperledger/fabric","slug":"the-identity-must-have-a-client-a-peer-an-ordere","errorCode":null,"errorMessage":"the identity must have a client, a peer, an orderer, or an admin OU role to be valid, not a combination of them. OUs: %s, MSP: [%s]","messagePattern":"the identity must have a client, a peer, an orderer, or an admin OU role to be valid, not a combination of them\\. OUs: (.+?), MSP: \\[(.+?)\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"msp/mspimplvalidate.go","lineNumber":287,"sourceCode":"\t\t}\n\n\t\t// Yes. Then, enforce the certifiers identifier in this is specified.\n\t\t// If is not specified, it means that any certification path is fine.\n\t\tif len(nodeOU.CertifiersIdentifier) != 0 && !bytes.Equal(nodeOU.CertifiersIdentifier, OU.CertifiersIdentifier) {\n\t\t\treturn errors.Errorf(\"certifiersIdentifier does not match: %s, MSP: [%s]\", OUIDs(id.GetOrganizationalUnits()), msp.name)\n\t\t}\n\t\tcounter++\n\t\tif counter > 1 {\n\t\t\tbreak\n\t\t}\n\t}\n\n\t// the identity should have exactly one OU role, return an error if the counter is not 1.\n\tif counter == 0 {\n\t\treturn errors.Errorf(\"the identity does not have an OU that resolves to client, peer, orderer, or admin role. OUs: %s, MSP: [%s]\", OUIDs(id.GetOrganizationalUnits()), msp.name)\n\t}\n\tif counter > 1 {\n\t\treturn errors.Errorf(\"the identity must have a client, a peer, an orderer, or an admin OU role to be valid, not a combination of them. OUs: %s, MSP: [%s]\", OUIDs(id.GetOrganizationalUnits()), msp.name)\n\t}\n\n\treturn nil\n}\n\nfunc (msp *bccspmsp) getValidityOptsForCert(cert *x509.Certificate) x509.VerifyOptions {\n\t// First copy the opts to override the CurrentTime field\n\t// in order to make the certificate passing the expiration test\n\t// independently from the real local current time.\n\t// This is a temporary workaround for FAB-3678\n\n\tvar tempOpts x509.VerifyOptions\n\ttempOpts.Roots = msp.opts.Roots\n\ttempOpts.DNSName = msp.opts.DNSName\n\ttempOpts.Intermediates = msp.opts.Intermediates\n\ttempOpts.KeyUsages = msp.opts.KeyUsages\n\ttempOpts.CurrentTime = cert.NotBefore.Add(time.Second)\n","sourceCodeStart":269,"sourceCodeEnd":305,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/msp/mspimplvalidate.go#L269-L305","documentation":"V1.4.2 OU validation found more than one role-matching OU (client/peer/orderer/admin) on the identity, so the role is ambiguous and the identity is rejected. An identity must represent exactly one role.","triggerScenarios":"msp.Validate(identity) where multiple OUs in the certificate match distinct or same configured role identifiers, making counter exceed 1 in validateIdentityOUsV142.","commonSituations":"Certificate subject containing multiple role OUs (OU=client plus OU=admin); MSP config with duplicated OrganizationalUnitIdentifier across role sections; certificate generated with extra RDN OUs.","solutions":["Reissue the certificate with exactly one role OU","Ensure each NodeOU role identifier has a unique OrganizationalUnitIdentifier","Strip extra OU attributes from the certificate request (CSR)"],"exampleFix":"// before CSR subject\nO = org, OU = admin, OU = client\n// after\nO = org, OU = admin","handlingStrategy":"validation","validationCode":"func countV142Roles(cert *x509.Certificate, roleOUs []string) int {\n    set := map[string]struct{}{}\n    for _, r := range roleOUs { set[r] = struct{}{} }\n    n := 0\n    for _, ou := range cert.Subject.OU {\n        if _, ok := set[ou]; ok { n++ }\n    }\n    return n\n}\n// count != 1 -> identity will be rejected as ambiguous or unclassified.","typeGuard":null,"tryCatchPattern":null,"preventionTips":["One role OU per certificate subject","Keep role OrganizationalUnitIdentifiers unique in NodeOUs","Lint CSRs/cert templates to forbid duplicate OU RDNs"],"tags":["fabric","msp","x509"],"backgroundTag":"msp-ou-validation-failed","analyzedSha":"2736b63f8fd5932511d56fe68b7039d15977f7f6","analyzedAt":"2026-09-04T08:52:36.465Z","contentChangedAt":"2026-09-04T08:52:36.465Z","schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}