{"record":{"id":"7aa9c99725f22ee5","repo":"hyperledger/fabric","slug":"cannot-test-for-classification-node-ou-for-type","errorCode":null,"errorMessage":"cannot test for classification, node ou for type [%s], not defined, msp: [%s]","messagePattern":"cannot test for classification, node ou for type \\[(.+?)\\], not defined, msp: \\[(.+?)\\]","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"msp/mspimpl.go","lineNumber":375,"sourceCode":"}\n\nfunc (msp *bccspmsp) hasOURoleInternal(id *identity, mspRole m.MSPRole_MSPRoleType) error {\n\tvar nodeOU *OUIdentifier\n\tswitch mspRole {\n\tcase m.MSPRole_CLIENT:\n\t\tnodeOU = msp.clientOU\n\tcase m.MSPRole_PEER:\n\t\tnodeOU = msp.peerOU\n\tcase m.MSPRole_ADMIN:\n\t\tnodeOU = msp.adminOU\n\tcase m.MSPRole_ORDERER:\n\t\tnodeOU = msp.ordererOU\n\tdefault:\n\t\treturn errors.New(\"Invalid MSPRoleType. It must be CLIENT, PEER, ADMIN or ORDERER\")\n\t}\n\n\tif nodeOU == nil {\n\t\treturn errors.Errorf(\"cannot test for classification, node ou for type [%s], not defined, msp: [%s]\", mspRole, msp.name)\n\t}\n\n\tfor _, OU := range id.GetOrganizationalUnits() {\n\t\tif OU.OrganizationalUnitIdentifier == nodeOU.OrganizationalUnitIdentifier {\n\t\t\treturn nil\n\t\t}\n\t}\n\n\treturn errors.Errorf(\"The identity does not contain OU [%s], MSP: [%s]\", mspRole, msp.name)\n}\n\n// DeserializeIdentity returns an Identity given the byte-level\n// representation of a SerializedIdentity struct\nfunc (msp *bccspmsp) DeserializeIdentity(serializedID []byte) (Identity, error) {\n\tmspLogger.Debug(\"Obtaining identity\")\n\n\t// We first deserialize to a SerializedIdentity to get the MSP ID\n\tsId := &m.SerializedIdentity{}","sourceCodeStart":357,"sourceCodeEnd":393,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/msp/mspimpl.go#L357-L393","documentation":"After mapping the requested MSPRole to a node OU, hasOURoleInternal checks whether that OU is configured in the MSP (clientOU/peerOU/adminOU/ordererOU). This error means the role is valid but the MSP configuration does not define the corresponding NodeOUs entry, so classification cannot be tested. It is a configuration-gap error in msp/mspimpl.go.","triggerScenarios":"Evaluating a NODE_OU principal for a role (e.g. ADMIN) while the MSP config's NodeOUs section omits that OU (or NodeOUs/OUIdentifiers are not enabled at all in config.yaml), via hasOURole during policy satisfaction checks.","commonSituations":"config.yaml lacking the NodeOUs block or the specific AdminOUIdentifiers/OrdererOUIdentifiers entries; upgrading a network that now uses NodeOUs-based ACLs while old MSP dirs have no NodeOUs; typo'd OU identifiers meaning the section was skipped.","solutions":["Add the missing NodeOUs entry (e.g. AdminOUIdentifiers) to the MSP's config.yaml and redeploy the MSP directory.","Enable NodeOUs: set NodeOUs.Enable: true and provide OUIdentifiers for all roles you evaluate policies against.","If the role classification isn't needed, change the policy principal to one backed by a defined OU (e.g. PEER) or use an explicit MSPRole/MSP member principal instead."],"exampleFix":"# before (config.yaml)\nNodeOUs:\n  Enable: true\n  ClientOUIdentifier:\n    Certificate: cacerts/cert.pem\n    OrganizationalUnitIdentifier: client\n# after\nNodeOUs:\n  Enable: true\n  ClientOUIdentifier:\n    Certificate: cacerts/cert.pem\n    OrganizationalUnitIdentifier: client\n  AdminOUIdentifier:\n    Certificate: cacerts/cert.pem\n    OrganizationalUnitIdentifier: admin","handlingStrategy":"validation","validationCode":"func mspDefinesNodeOU(cfg *msp.MSPConfig, role string) bool {\n  var conf m.FabricMSPConfig\n  if err := proto.Unmarshal(cfg.Config, &conf); err != nil {\n    return false\n  }\n  if conf.NodeOus == nil {\n    return false\n  }\n  switch role {\n  case \"client\":\n    return conf.NodeOus.ClientOuIdentifier != nil\n  case \"peer\":\n    return conf.NodeOus.PeerOuIdentifier != nil\n  case \"admin\":\n    return conf.NodeOus.AdminOuIdentifier != nil\n  case \"orderer\":\n    return conf.NodeOus.OrdererOuIdentifier != nil\n  }\n  return false\n}","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always include the full NodeOUs block (client/peer/admin/orderer identifiers) in MSP config.yaml when using OU-based policies.","Cryptogen/configtxgen output should be audited for NodeOUs before network launch.","Validate MSP directories in CI by unmarshaling FabricMSPConfig and checking required OU identifiers."],"tags":["msp","node-ou","config","policy"],"backgroundTag":"missing-msp-nodeou-config","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"}