{"record":{"id":"1d0d80f15a270230","repo":"temporalio/temporal","slug":"w-id-is-d-but-must-be-d","errorCode":null,"errorMessage":"%w: id is %d but must be >= %d","messagePattern":"%w: id is (.+?) but must be >= (.+?)","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"common/persistence/sql/queue_v2.go","lineNumber":227,"sourceCode":"\t\t)\n\t}\n\tif err != nil {\n\t\treturn nil, serviceerror.NewUnavailablef(\n\t\t\t\"CreateQueue failed for queue with type: %v and name: %v. InsertIntoQueueV2Metadata operation failed. Error: %v\",\n\t\t\trequest.QueueType,\n\t\t\trequest.QueueName,\n\t\t\terr,\n\t\t)\n\t}\n\treturn &persistence.InternalCreateQueueResponse{}, nil\n}\n\nfunc (q *queueV2) RangeDeleteMessages(\n\tctx context.Context,\n\trequest *persistence.InternalRangeDeleteMessagesRequest,\n) (*persistence.InternalRangeDeleteMessagesResponse, error) {\n\tif request.InclusiveMaxMessageMetadata.ID < persistence.FirstQueueMessageID {\n\t\treturn nil, fmt.Errorf(\n\t\t\t\"%w: id is %d but must be >= %d\",\n\t\t\tpersistence.ErrInvalidQueueRangeDeleteMaxMessageID,\n\t\t\trequest.InclusiveMaxMessageMetadata.ID,\n\t\t\tpersistence.FirstQueueMessageID,\n\t\t)\n\t}\n\tvar resp *persistence.InternalRangeDeleteMessagesResponse\n\terr := q.txExecute(ctx, \"RangeDeleteMessages\", func(tx sqlplugin.Tx) error {\n\t\tqm, err := q.getQueueMetadata(ctx, tx, request.QueueType, request.QueueName)\n\t\tif err != nil {\n\t\t\treturn err\n\t\t}\n\t\tpartition, err := persistence.GetPartitionForQueueV2(request.QueueType, request.QueueName, qm)\n\t\tif err != nil {\n\t\t\treturn serviceerror.NewUnavailablef(\n\t\t\t\t\"RangeDeleteMessages failed for queue with type: %v and name: %v. GetPartitionForQueueV2 operation failed. Error: %v\",\n\t\t\t\trequest.QueueType,\n\t\t\t\trequest.QueueName,","sourceCodeStart":209,"sourceCodeEnd":245,"githubUrl":"https://github.com/temporalio/temporal/blob/bde624efd13fbd3843654058db6d9c716166318b/common/persistence/sql/queue_v2.go#L209-L245","documentation":"RangeDeleteMessages validates that InclusiveMaxMessageMetadata.ID is at least persistence.FirstQueueMessageID; if a smaller (e.g., zero or negative) ID is passed, it returns ErrInvalidQueueRangeDeleteMaxMessageID wrapped with the offending value. It is a pure input-validation guard before any database work.","triggerScenarios":"Calling RangeDeleteMessages with InternalRangeDeleteMessagesRequest.InclusiveMaxMessageMetadata.ID < FirstQueueMessageID (e.g., 0 from an uninitialized struct or a default-valued message ID).","commonSituations":"Caller passes a zero-value struct with the max-message ID never populated; off-by-one arithmetic producing 0; deserializing a request whose ID field was never set.","solutions":["Set InclusiveMaxMessageMetadata.ID to a valid message ID >= FirstQueueMessageID before calling.","Obtain the actual last message ID from the queue (e.g., from GetQueueMetadata/message count APIs) instead of a hardcoded 0.","If deleting everything, fetch the current max message ID and pass that as the inclusive max."],"exampleFix":"// before\nreq := &persistence.InternalRangeDeleteMessagesRequest{} // ID defaults to 0\nstore.RangeDeleteMessages(ctx, req)\n// after\nreq := &persistence.InternalRangeDeleteMessagesRequest{\n    InclusiveMaxMessageMetadata: &persistencespb.QueueMessageMetadata{ID: actualMaxID},\n}\nstore.RangeDeleteMessages(ctx, req)","handlingStrategy":"validation","validationCode":"if req.InclusiveMaxMessageMetadata == nil || req.InclusiveMaxMessageMetadata.ID < persistence.FirstQueueMessageID {\n    return fmt.Errorf(\"inclusive max message ID must be >= %d\", persistence.FirstQueueMessageID)\n}\n// safe to call RangeDeleteMessages","typeGuard":null,"tryCatchPattern":"if errors.Is(err, persistence.ErrInvalidQueueRangeDeleteMaxMessageID) {\n    // fix caller: fetch real max message ID and retry once\n}","preventionTips":["Never pass zero-value request structs; always populate the inclusive max message metadata.","Fetch the current max message ID from queue metadata before range deletes.","Add caller-side assertions on message IDs before persistence calls."],"tags":["validation","queue","input-error"],"backgroundTag":"invalid-argument-range","analyzedSha":"bde624efd13fbd3843654058db6d9c716166318b","analyzedAt":"2026-09-01T07:18:39.080Z","contentChangedAt":null,"schemaVersion":2},"datasetVersion":"2026-09-08T10:18:20.063Z"}