diff --git a/endpoints/openrtb2/auction.go b/endpoints/openrtb2/auction.go index fd1803597c3..e3f079d4c4c 100644 --- a/endpoints/openrtb2/auction.go +++ b/endpoints/openrtb2/auction.go @@ -491,21 +491,27 @@ func fillAndValidateNativeAssets(assets []nativeRequests.Asset, impIndex int) er return fmt.Errorf("request.imp[%d].native.request.assets must be an array containing at least one object", impIndex) } + assetIDs := make(map[uint64]bool, len(assets)) + for i := 0; i < len(assets); i++ { - // Per the OpenRTB spec docs, this is a "unique asset ID, assigned by exchange. Typically a counter for the array" - // To avoid conflict with the Request, we'll return a 400 if the Request _did_ define this ID, - // and then populate it as the spec suggests. if err := validateNativeAsset(assets[i], impIndex, i); err != nil { return err } - assets[i].ID = int64(i) + + // Each asset should have a unique ID thats assigned by the caller + if _, ok := assetIDs[assets[i].ID]; ok { + return fmt.Errorf("request.imp[%d].native.request.assets[%d].id is already being used by another asset. Each asset ID must be unique.", impIndex, i) + } + + assetIDs[assets[i].ID] = true } + return nil } func validateNativeAsset(asset nativeRequests.Asset, impIndex int, assetIndex int) error { - if asset.ID != 0 { - return fmt.Errorf(`request.imp[%d].native.request.assets[%d].id must not be defined. Prebid Server will set this automatically, using the index of the asset in the array as the ID`, impIndex, assetIndex) + if asset.ID == 0 { + return fmt.Errorf(`request.imp[%d].native.request.assets[%d].id must be defined by the caller`, impIndex, assetIndex) } assetErr := "request.imp[%d].native.request.assets[%d] must define exactly one of {title, img, video, data}"