{"record":{"id":"5ebb2cfe549320b3","repo":"hyperledger/fabric","slug":"fields-definition-must-be-an-array","errorCode":null,"errorMessage":"fields definition must be an array","messagePattern":"fields definition must be an array","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"core/ledger/kvledger/txmgmt/statedb/statecouchdb/statecouchdb.go","lineNumber":976,"sourceCode":"\tconst jsonQueryFields = \"fields\"\n\tconst jsonQueryLimit = \"limit\"\n\tconst jsonQueryBookmark = \"bookmark\"\n\t// create a generic map for the query json\n\tjsonQueryMap := make(map[string]any)\n\t// unmarshal the selector json into the generic map\n\tdecoder := json.NewDecoder(bytes.NewBuffer([]byte(queryString)))\n\tdecoder.UseNumber()\n\terr := decoder.Decode(&jsonQueryMap)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tif fieldsJSONArray, ok := jsonQueryMap[jsonQueryFields]; ok {\n\t\tswitch fieldsJSONArray := fieldsJSONArray.(type) {\n\t\tcase []any:\n\t\t\t// Add the \"_id\", and \"version\" fields,  these are needed by default\n\t\t\tjsonQueryMap[jsonQueryFields] = append(fieldsJSONArray, idField, versionField)\n\t\tdefault:\n\t\t\treturn \"\", errors.New(\"fields definition must be an array\")\n\t\t}\n\t}\n\t// Add limit\n\t// This will override any limit passed in the query.\n\t// Explicit paging not yet supported.\n\tjsonQueryMap[jsonQueryLimit] = queryLimit\n\t// Add the bookmark if provided\n\tif queryBookmark != \"\" {\n\t\tjsonQueryMap[jsonQueryBookmark] = queryBookmark\n\t}\n\t// Marshal the updated json query\n\teditedQuery, err := json.Marshal(jsonQueryMap)\n\tif err != nil {\n\t\treturn \"\", err\n\t}\n\tlogger.Debugf(\"Rewritten query: %s\", editedQuery)\n\treturn string(editedQuery), nil\n}","sourceCodeStart":958,"sourceCodeEnd":994,"githubUrl":"https://github.com/hyperledger/fabric/blob/2736b63f8fd5932511d56fe68b7039d15977f7f6/core/ledger/kvledger/txmgmt/statedb/statecouchdb/statecouchdb.go#L958-L994","documentation":"applyAdditionalQueryOptions rewrites the CouchDB Mango query JSON, injecting required fields ('_id' and 'version') into the 'fields' selector. If 'fields' is present but is not a JSON array, the rewrite cannot proceed and this error is returned.","triggerScenarios":"Executing a rich query via ExecuteQueryWithPagination (or executeQueryWithBookmark) whose JSON contains a \"fields\" key with a non-array value, e.g. \"fields\": \"name\" or \"fields\": {\"name\":1}.","commonSituations":"Translating Mongo-style projections (object form) into Mango queries; hand-written queries with 'fields' as a string; dynamic query builders that mis-serialize the projection.","solutions":["Change \"fields\" in the query JSON to an array of field names, e.g. \"fields\": [\"name\",\"owner\"].","Remove the \"fields\" clause entirely; the framework adds the required _id/version fields automatically.","Validate the query JSON shape in the client before invoking the query.","If porting from MongoDB syntax, convert projection objects {field:1} into Mango arrays [field]."],"exampleFix":"// before\n{\"selector\":{\"owner\":\"alice\"},\"fields\":{\"name\":1}}\n// after\n{\"selector\":{\"owner\":\"alice\"},\"fields\":[\"name\"]}","handlingStrategy":"validation","validationCode":"func validateMangoQuery(q string) error {\n  var m map[string]any\n  if err := json.Unmarshal([]byte(q), &m); err != nil { return err }\n  if f, ok := m[\"fields\"]; ok {\n    if _, isArray := f.([]any); !isArray {\n      return errors.New(\"'fields' must be a JSON array of field names\")\n    }\n  }\n  return nil\n}","typeGuard":"func fieldsIsArray(query map[string]any) bool {\n  f, ok := query[\"fields\"]\n  if !ok { return true }\n  _, isArray := f.([]any)\n  return isArray\n}","tryCatchPattern":"iter, err := ctx.GetStub().GetQueryResult(query)\nif err != nil {\n  return fmt.Errorf(\"rich query rejected (check 'fields' is an array): %w\", err)\n}","preventionTips":["Author Mango queries with array-form 'fields' selectors","Never translate MongoDB projection objects {field:1} directly into Mango queries","Test rich queries against the target network before chaincode upgrade"],"tags":["couchdb","rich-query","json-validation","mango"],"backgroundTag":"invalid-query-shape","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"}