{"record":{"id":"a9c9db2edda5be3b","repo":"hyperledger/fabric","slug":"chaincode-s-does-not-require-initialization-but","errorCode":null,"errorMessage":"chaincode '%s' does not require initialization but called as init","messagePattern":"chaincode '(.+?)' does not require initialization but called as init","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/chaincode/chaincode_support.go","lineNumber":247,"sourceCode":"\t}\n\n\tneedsInitialization := false\n\tif cii.EnforceInit {\n\n\t\tvalue, err := txParams.TXSimulator.GetState(chaincodeName, InitializedKeyName)\n\t\tif err != nil {\n\t\t\treturn \"\", 0, errors.WithMessage(err, \"could not get 'initialized' key\")\n\t\t}\n\n\t\tneedsInitialization = !bytes.Equal(value, []byte(cii.Version))\n\t}\n\n\t// Note, IsInit is a new field for v2.0 and should only be set for invocations of non-legacy chaincodes.\n\t// Any invocation of a legacy chaincode with IsInit set will fail.  This is desirable, as the old\n\t// InstantiationPolicy contract enforces which users may call init.\n\tif input.IsInit {\n\t\tif !cii.EnforceInit {\n\t\t\treturn \"\", 0, errors.Errorf(\"chaincode '%s' does not require initialization but called as init\", chaincodeName)\n\t\t}\n\n\t\tif !needsInitialization {\n\t\t\treturn \"\", 0, errors.Errorf(\"chaincode '%s' is already initialized but called as init\", chaincodeName)\n\t\t}\n\n\t\terr = txParams.TXSimulator.SetState(chaincodeName, InitializedKeyName, []byte(cii.Version))\n\t\tif err != nil {\n\t\t\treturn \"\", 0, errors.WithMessage(err, \"could not set 'initialized' key\")\n\t\t}\n\n\t\treturn cii.ChaincodeID, pb.ChaincodeMessage_INIT, nil\n\t}\n\n\tif needsInitialization {\n\t\treturn \"\", 0, errors.Errorf(\"chaincode '%s' has not been initialized for this version, must call as init first\", chaincodeName)\n\t}\n","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/chaincode/chaincode_support.go#L229-L265","documentation":"In Fabric v2.0, chaincodes that require explicit initialization enforce 'init exactly once' semantics via an 'initialized' key in their namespace. This error is returned by CheckInvocation when the client sets input.IsInit=true but the chaincode's definition has EnforceInit=false — i.e. this chaincode does not use the new --init-required flow, so calling it 'as init' is invalid. Legacy (v1.x) chaincodes are the typical case, since old InstantiationPolicy rules govern them and IsInit is rejected.","triggerScenarios":"Calling ChaincodeSupport.Invoke (client-side 'peer chaincode invoke -isInit' or SDK equivalents) with IsInit=true against a chaincode whose endorsement info reports EnforceInit==false (deployed without --init-required, or a v1.x legacy chaincode).","commonSituations":"Client/SDK sending isInit:true by default against a chaincode committed with --init-required omitted; invoking a legacy v1.x chaincode upgraded onto a v2 peer with isInit set; mixing SDK init flags with old instantiation flow.","solutions":["Remove the isInit flag from the invocation and call the chaincode as a normal transaction.","If init semantics are actually required, redefine the chaincode as v2 format with '--init-required' during approve/commit so EnforceInit becomes true.","For legacy chaincodes, use the old instantiation path instead of the v2 IsInit mechanism.","Update SDK/client code to only set isInit when the committed definition specifies initRequired:true."],"exampleFix":"// before\nargs := [][]byte{[]byte(\"Init\"), []byte(\"a\"), []byte(\"100\")}\nreq := channel.Request{ChaincodeID: \"mycc\", Fcn: \"init\", Args: args, IsInit: true}\n// after (chaincode committed without --init-required)\nreq := channel.Request{ChaincodeID: \"mycc\", Fcn: \"init\", Args: args} // no IsInit","handlingStrategy":"validation","validationCode":"// only set isInit when the committed definition requires init\ncommitted, _ := queryCommitted(channelName, chaincodeName) // e.g. via peer CLI/SDK\nrequireInit := committed != nil && committed.InitRequired\nif wantInit && !requireInit {\n    return fmt.Errorf(\"chaincode %s does not require init; drop the isInit flag\", chaincodeName)\n}","typeGuard":"func isInitFlagMismatch(err error, chaincodeName string) bool {\n    return err != nil && strings.Contains(err.Error(),\n        fmt.Sprintf(\"chaincode '%s' does not require initialization but called as init\", chaincodeName))\n}","tryCatchPattern":null,"preventionTips":["Set isInit only when the chaincode was committed with '--init-required'.","Never set isInit for legacy (v1.x format) chaincodes on v2 peers.","Audit SDK/client defaults — some SDKs expose init flags that must be explicitly disabled.","Call Init as a separate first transaction (with isInit) then normal invokes, only for init-required chaincodes.","Document per-chaincode whether init is required to prevent client-side misuse."],"tags":["lifecycle","init-required","hyperledger-fabric","v2-migration"],"backgroundTag":"chaincode-init-mismatch","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"}