{"record":{"id":"d6b94ccf4cf04f3e","repo":"openimsdk/open-im-server","slug":"size-must-be-greater-than-0","errorCode":null,"errorMessage":"size must be greater than 0","messagePattern":"size must be greater than 0","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"pkg/common/storage/database/mgo/seq_conversation.go","lineNumber":53,"sourceCode":"\tinsert := bson.M{\n\t\t\"conversation_id\": conversationID,\n\t\t\"min_seq\":         0,\n\t\t\"max_seq\":         0,\n\t}\n\tdelete(insert, field)\n\tupdate := map[string]any{\n\t\t\"$set\": bson.M{\n\t\t\tfield: seq,\n\t\t},\n\t\t\"$setOnInsert\": insert,\n\t}\n\topt := options.Update().SetUpsert(true)\n\treturn mongoutil.UpdateOne(ctx, s.coll, filter, update, false, opt)\n}\n\nfunc (s *seqConversationMongo) Malloc(ctx context.Context, conversationID string, size int64) (int64, error) {\n\tif size < 0 {\n\t\treturn 0, errors.New(\"size must be greater than 0\")\n\t}\n\tif size == 0 {\n\t\treturn s.GetMaxSeq(ctx, conversationID)\n\t}\n\tfilter := map[string]any{\"conversation_id\": conversationID}\n\tupdate := map[string]any{\n\t\t\"$inc\":         map[string]any{\"max_seq\": size},\n\t\t\"$setOnInsert\": map[string]any{\"min_seq\": int64(0)},\n\t}\n\topt := options.FindOneAndUpdate().SetUpsert(true).SetReturnDocument(options.After).SetProjection(map[string]any{\"_id\": 0, \"max_seq\": 1})\n\tlastSeq, err := mongoutil.FindOneAndUpdate[int64](ctx, s.coll, filter, update, opt)\n\tif err != nil {\n\t\treturn 0, err\n\t}\n\treturn lastSeq - size, nil\n}\n\nfunc (s *seqConversationMongo) SetMaxSeq(ctx context.Context, conversationID string, seq int64) error {","sourceCodeStart":35,"sourceCodeEnd":71,"githubUrl":"https://github.com/openimsdk/open-im-server/blob/175a7bb0673eca18e9d1b10bff4f728da6b1b513/pkg/common/storage/database/mgo/seq_conversation.go#L35-L71","documentation":"seqConversationMongo.Malloc allocates a block of sequence numbers for a conversation. It rejects negative sizes up front with this error, treating them as a caller bug; a size of 0 is allowed and simply returns the current max seq without allocating. This is an argument-validation guard, not a storage failure.","triggerScenarios":"Calling Malloc(ctx, conversationID, size) with size < 0, typically from computing an allocation count via subtraction (e.g. count = target - current) that underflows, or passing an uninitialized/negative int64.","commonSituations":"Message counters or batch allocators computed as a difference of seqs going negative; int64 underflow after wraparound; passing a config value that defaulted to -1 meaning 'unset'.","solutions":["Inspect the caller's size computation and clamp negative values to 0 or skip the Malloc call entirely.","Validate size > 0 (or >= 0) at the caller boundary before invoking Malloc.","Check for integer underflow when size is derived from subtracting sequence numbers."],"exampleFix":"// before\nseq, err := seqConv.Malloc(ctx, convID, target-current)\n// after\nn := target - current\nif n <= 0 {\n    return nil\n}\nseq, err := seqConv.Malloc(ctx, convID, n)","handlingStrategy":"validation","validationCode":"if size <= 0 {\n    return errors.New(\"malloc size must be positive\")\n}","typeGuard":"func validMallocSize(size int64) bool { return size > 0 }","tryCatchPattern":null,"preventionTips":["Clamp seq-derived sizes: if n := target - current; n <= 0 { skip allocation }","Treat config defaults of -1 as 'unset' before passing to Malloc"],"tags":["validation","mongodb","sequence"],"backgroundTag":"invalid-argument-value","analyzedSha":"175a7bb0673eca18e9d1b10bff4f728da6b1b513","analyzedAt":"2026-09-04T16:52:56.821Z","contentChangedAt":"2026-09-04T16:52:56.821Z","schemaVersion":2},"datasetVersion":"2026-09-11T21:17:09.523Z"}