{"record":{"id":"d6bbb42aff75e8ac","repo":"hyperledger/fabric","slug":"invalid-key-s-cannot-begin-with","errorCode":null,"errorMessage":"invalid key [%s], cannot begin with \"_\"","messagePattern":"invalid key \\[(.+?)\\], cannot begin with \"_\"","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdoc_conv.go","lineNumber":291,"sourceCode":"\t\treturn \"\", err\n\t}\n\treturn dataformatInfo.Version, nil\n}\n\nfunc validateValue(value []byte) error {\n\tisJSON, jsonVal := tryCastingToJSON(value)\n\tif !isJSON {\n\t\treturn nil\n\t}\n\treturn jsonVal.checkReservedFieldsNotPresent()\n}\n\nfunc validateKey(key string) error {\n\tif !utf8.ValidString(key) {\n\t\treturn errors.Errorf(\"invalid key [%x], must be a UTF-8 string\", key)\n\t}\n\tif strings.HasPrefix(key, \"_\") {\n\t\treturn errors.Errorf(\"invalid key [%s], cannot begin with \\\"_\\\"\", key)\n\t}\n\tif key == \"\" {\n\t\treturn errors.New(\"invalid key. Empty string is not supported as a key by couchdb\")\n\t}\n\treturn nil\n}\n\n// removeJSONRevision removes the \"_rev\" if this is a JSON\nfunc removeJSONRevision(jsonValue *[]byte) error {\n\tjsonVal, err := castToJSON(*jsonValue)\n\tif err != nil {\n\t\tlogger.Errorf(\"Failed to unmarshal couchdb JSON data: %+v\", err)\n\t\treturn err\n\t}\n\tjsonVal.removeRevField()\n\tif *jsonValue, err = jsonVal.toBytes(); err != nil {\n\t\tlogger.Errorf(\"Failed to marshal couchdb JSON data: %+v\", err)\n\t}","sourceCodeStart":273,"sourceCodeEnd":309,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/kvledger/txmgmt/statedb/statecouchdb/couchdoc_conv.go#L273-L309","documentation":"validateKey enforces CouchDB document-key rules before a key becomes a CouchDB _id. Keys starting with an underscore are rejected because CouchDB reserves the '_'-prefixed field names (like _id, _rev, _design) for its own document metadata; storing such a key would collide with that namespace.","triggerScenarios":"Calling ValidateKeyValue with a key whose first character is '_' (e.g. a state key literally named '_config' or '_temp'), or reading a record from the DB (readFromDB) whose stored key begins with '_' — typically after a write that bypassed validation or an external import.","commonSituations":"Chaincode or migration tooling generating keys from JSON field names that start with '_'; importing legacy data into a CouchDB-backed ledger; keys constructed by concatenating prefixes that produce a leading underscore.","solutions":["Rename the key so it does not start with '_' (prefix with a safe character, e.g. 'x_' or strip/replace the leading underscore).","Sanitize keys at the application boundary before PutState, rejecting or remapping underscore-prefixed names.","If the data came from an import/migration, re-run the migration with key transformation applied.","If the key must start with '_' semantically, use LevelDB (stateleveldb) as the state database instead of CouchDB."],"exampleFix":"// before\nctx.GetStub().PutState(\"_userCounter\", []byte(\"1\"))\n// after\nctx.GetStub().PutState(\"userCounter\", []byte(\"1\"))","handlingStrategy":"validation","validationCode":"func validStateKey(key string) error {\n  if !utf8.ValidString(key) { return fmt.Errorf(\"key not UTF-8: %x\", key) }\n  if strings.HasPrefix(key, \"_\") { return fmt.Errorf(\"key must not start with '_': %s\", key) }\n  if key == \"\" { return errors.New(\"key must be non-empty\") }\n  return nil\n}\n// call before PutState\nif err := validStateKey(key); err != nil { return err }","typeGuard":"func isSafeKey(key string) bool {\n  return key != \"\" && !strings.HasPrefix(key, \"_\") && utf8.ValidString(key)\n}","tryCatchPattern":null,"preventionTips":["Never build state keys from raw JSON field names without sanitizing leading underscores","Centralize key construction in one helper that enforces the no-leading-underscore rule","Add unit tests that reject keys like \"_id\", \"_rev\", \"\" before they reach PutState"],"tags":["couchdb","state-database","validation","ledger"],"backgroundTag":"reserved-key-name","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"}