{"record":{"id":"1a9785f74437ab88","repo":"hyperledger/fabric","slug":"nil-signer-provided","errorCode":null,"errorMessage":"nil signer provided","messagePattern":"nil signer provided","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"internal/peer/lifecycle/chaincode/approveformyorg.go","lineNumber":279,"sourceCode":"\t\tVersion:                  chaincodeVersion,\n\t\tPackageID:                packageID,\n\t\tSequence:                 int64(sequence),\n\t\tEndorsementPlugin:        endorsementPlugin,\n\t\tValidationPlugin:         validationPlugin,\n\t\tValidationParameterBytes: policyBytes,\n\t\tInitRequired:             initRequired,\n\t\tCollectionConfigPackage:  ccp,\n\t\tPeerAddresses:            peerAddresses,\n\t\tWaitForEvent:             waitForEvent,\n\t\tWaitForEventTimeout:      waitForEventTimeout,\n\t}\n\n\treturn input, nil\n}\n\nfunc (a *ApproverForMyOrg) createProposal(inputTxID string) (proposal *pb.Proposal, txID string, err error) {\n\tif a.Signer == nil {\n\t\treturn nil, \"\", errors.New(\"nil signer provided\")\n\t}\n\n\tvar ccsrc *lb.ChaincodeSource\n\tif a.Input.PackageID != \"\" {\n\t\tccsrc = &lb.ChaincodeSource{\n\t\t\tType: &lb.ChaincodeSource_LocalPackage{\n\t\t\t\tLocalPackage: &lb.ChaincodeSource_Local{\n\t\t\t\t\tPackageId: a.Input.PackageID,\n\t\t\t\t},\n\t\t\t},\n\t\t}\n\t} else {\n\t\tccsrc = &lb.ChaincodeSource{\n\t\t\tType: &lb.ChaincodeSource_Unavailable_{\n\t\t\t\tUnavailable: &lb.ChaincodeSource_Unavailable{},\n\t\t\t},\n\t\t}\n\t}","sourceCodeStart":261,"sourceCodeEnd":297,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/internal/peer/lifecycle/chaincode/approveformyorg.go#L261-L297","documentation":"createProposal on ApproverForMyOrg requires a signer (the peer CLI's local MSP identity) to build and sign the proposal. If a.Signer is nil, the command cannot construct a signed transaction, so it returns 'nil signer provided' immediately. This is a client-side precondition check, not a network or peer failure.","triggerScenarios":"Calling approveformyorg (or invoking createProposal directly in Go code) without specifying -o orderer/peer connection info that yields a signing identity — i.e. no --peerAddress/--tlsRootCertFile + MSP context, or constructing ApproverForMyOrg with Signer unset when the common.Input lacks the signing identity parameters.","commonSituations":"Forgetting --peerAddress / --connTimeout or running outside an admin CLI context where the local MSP path (FABRIC_CFG_PATH, CORE_PEER_LOCALMSPID, CORE_PEER_MSPCONFIGPATH) is not configured, so no signer can be loaded.","solutions":["Set the signing identity env: CORE_PEER_LOCALMSPID and CORE_PEER_MSPCONFIGPATH pointing to an admin user's MSP directory.","When invoking the underlying Go API directly, pass a valid common.Input including PeerAddress and ConnTimeout so InitCallerForMyOrg resolves a Signer before createProposal runs.","Verify FABRIC_CFG_PATH/core.yaml is readable and the MSP directory contains signcerts and keystore files.","Re-run the command with a peer address (-A/--peerAddresses) so the client builds a signer from that peer connection."],"exampleFix":"// before: API call with no signer wired\napprover := &chaincode.ApproverForMyOrg{...} // Signer == nil\n// after: initialize signer via InitCallerForMyOrg with peer connection info\ninput := &chaincode.CommonInput{PeerAddress: \"peer0.org1:7051\", ConnTimeout: 5 * time.Second}\napprover, err := chaincode.InitApproverForMyOrg(\"mychannel\", input)\n// Signer is now populated from local MSP","handlingStrategy":"validation","validationCode":"// before invoking approve, ensure a signing identity is configured\nif os.Getenv(\"CORE_PEER_MSPCONFIGPATH\") == \"\" || os.Getenv(\"CORE_PEER_LOCALMSPID\") == \"\" {\n    return errors.New(\"signing identity not configured: set CORE_PEER_MSPCONFIGPATH and CORE_PEER_LOCALMSPID\")\n}\nif _, err := os.Stat(os.Getenv(\"CORE_PEER_MSPCONFIGPATH\") + \"/signcerts\"); err != nil {\n    return fmt.Errorf(\"invalid MSP dir: %w\", err)\n}","typeGuard":"// in Go, guard before building the proposal\nfunc hasSigner(a *chaincode.ApproverForMyOrg) bool {\n    return a != nil && a.Signer != nil\n}","tryCatchPattern":"_, err := approver.Approve(proposal)\nif err != nil && strings.Contains(err.Error(), \"nil signer\") {\n    return fmt.Errorf(\"configure signing identity (CORE_PEER_MSPCONFIGPATH / peer address): %w\", err)\n}","preventionTips":["Export CORE_PEER_LOCALMSPID and CORE_PEER_MSPCONFIGPATH in every CLI session (or source the env script).","Pass --peerAddresses and --tlsRootCertFile so the client initializes a signer from peer connection inputs.","Verify FABRIC_CFG_PATH points to a valid config dir with core.yaml.","In Go callers, always construct the approver via InitApproverForMyOrg rather than a bare struct literal."],"tags":["fabric","signing","identity","cli-config"],"backgroundTag":"missing-signer-identity","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"}