Critical Issues with Roblox Changing 2D Clothing Items to "Collectible Item" Product Type

:warning: This is a highly in-depth report on issues that have severely impacted developer workflows and caused major disruptions in top Roblox games.


Recently, Roblox has begun altering the product type of 2D clothing items (such as T-shirts, shirts, pants, etc.) from the previously used “User Product” type to “Collectible Item.” Whether this change was intentional or not, it has caused major disruptions for developers and their workflows, especially in majorly popular games. This change is especially impactful on donation-based games like PLS DONATE, which had to remove support for catalog items from player stands, meaning donations can no longer happen through these items, greatly impacting its core functionality. Other top games, such as Catalog Avatar Creator (owned by @ItsMuneeeb), are also likely affected by this.

The ripple effect of this issue is massive—many developer workflows that rely on external APIs (such as MarketplaceService:GetProductInfo() or Roblox’s economy, marketplace, and catalog APIs) are now broken due to this backend data change. This is catastrophic for developers who have built robust systems around these APIs, including myself.

The Problem:

Apologies for the redundancy in some of the points here.

  1. Backend Data Changes for 2D Clothing:
    • Previously, the ProductType field for 2D clothing items was returned as "User Product" in API requests.
    • Now, some 2D clothing items are randomly being updated to "Collectible Item", while others remain "User Product". There appears to be no consistent pattern—some old assets have changed, while others, even newer ones, remain unaffected.
    • For example, the economy API response for asset 6948637552 shows the expected "User Product" behavior:
      {
        "TargetId": 6948637552,
        "ProductType": "User Product",
        "AssetId": 6948637552,
        ...
      }
      
    • However, newer assets (and some totally random older ones that Roblox has decided to migrate, e.g., from 2017) return "Collectible Item". Example:
      {
        "TargetId": 0,
        "ProductType": "Collectible Item",
        "AssetId": 121292848668647,
        ...
      }
      
  • Something interesting I found is that older items that were migrated (at least, the ones I tested) have their TargetId field populated correctly, whereas newly created ones that exhibit the issue have theirs set to 0, which is detrimental to existing workflows.
  1. Randomly Affected Assets:

    • It’s not only newer items being affected by this change. Some older items, like a shirt created in 2017 (915066971), are now incorrectly returning "Collectible Item" data, despite no updates being made to the item recently.
    • This inconsistency between assets with identical types and creators is causing major disruption.
  2. UX Differences in Creator Hub:

    • Not a huge issue but worth noting. Items marked as "Collectible Item" have slightly different UI in the Creator Hub compared to "User Product" items. Specifically, the publish/save button is a different style and has different text and functionality, which is another messy issue caused by this rollout. The UX should be the same regardless of whether or not the items have undergone the migration–they are the same type.
  3. TargetId Field Returning 0:

    • The TargetId field, which many developers use to cross-reference and verify assets, is now returning 0 for newer items marked as "Collectible Item". This breaks in-game systems relying on TargetId for purchase validation or item identification.

Major Impacts:

  1. Game Functionality Broken:

    • Many games use ProductType == "User Product" to ensure items are 2D clothing, filtering them from other types. The shift to "Collectible Item" has made it impossible to differentiate properly, breaking critical game workflows.
    • No workarounds exist except manually checking AssetTypeId, which is far more complex and unnecessary when the ProductType should suffice.
  2. Breaking Purchase Validation:

    • Critical Issue: A central component of player-to-player catalog asset purchase validation is broken due to this change. The API (details shared in private PM) used for verification no longer works with "Collectible Item" types, making it impossible to validate UGC clothing purchases and process donations properly.
    • This impacts the core functionality of these donation games and has led to the removal of its support for UGC catalog items.
  3. Developer Workflows Shattered:

    • External tools and systems relying on Roblox’s economy, marketplace, and catalog APIs are now completely unreliable. The inconsistent data from "Collectible Item" versus "User Product" makes it impossible to maintain working external applications or systems.
  4. Zero Developer Communication:

    • There was no advanced notice given to developers about this change which amazes me. If this is an intentional update, it is baffling that such a significant shift was rolled out randomly, with no prior announcement or timeline. This is a prime example of a botched rollout, showing zero regard for developer workflows. If it is intended, I’m not sure why half of the current catalog items are affected whilst the other half aren’t.

Possible Solutions:

  1. Roll Back Changes:

    • Ideally, Roblox should roll back all affected assets to the previous "User Product" type and give developers advanced notice beforehand if this change is reintroduced.
    • Ideally, as has been the case with similar breaking changes, developers should receive clear communication, a timeline, and a universal implementation across all items (instead of this random approach where only certain items are affected).
  2. Fix the TargetId Field:

    • The TargetId field should never return 0. This is a major oversight that should be urgently corrected.
  3. Fix API for Purchase Validation:

    • The API (see attached PM) used in donation games should be updated to handle "Collectible Item" types correctly, allowing purchase validation workflows to continue without breaking. Elsewise, other APIs should be modified to have the same behavior as this one and act as a drop-in replacement.
  4. Consistent UX:

    • Ensure that "Collectible Item" workflows in the Creator Hub match the original "User Product" workflows for consistency and better user experience.

And finally:

This change has decimated games and destroyed developer workflows that relied on consistent API data. Roblox has a history of being cautious about backward compatibility and quite literally refuses to fix long-standing bugs for this very reason, yet this rollout shows a shocking disregard for developers’ needs. Immediate action is required to fix these issues, as developers cannot adjust to a broken system with inconsistent and undocumented changes.

Further details on the API that doesn’t work with newer products are available via the attached private message.

CC’ing @GyroEffects, @bunnyc1986 and @BrightYellowElephant here.

A private message is associated with this bug report

13 Likes

Thanks for the report. We have assigned it to our team for review.

1 Like

The TargetId in the AssetV2 API response has been updated to be consistent with other ProductType.

1 Like

Thank you for your note. Regarding your concerns:

TargetId Issue in economy api

  • The bug has been fixed and deployed.

Determining assetType

  • Using productType is not recommended. There’s no relationship between product type and asset type. We suggest using the public catalog API to properly differentiate asset types.

Some are collectible item, some are not

  • The migration involves a large amount of data, so some assets have already been migrated while others are still in progress. This process will take additional time to complete.
  • Eventually every avatar item is a Collectible Item.

Purchase validation Issue

  • The original method of performing price validation through the developer-product API was not meant to work. This api was developed for dev-product and it is deprecated.

  • We’d like to offer some alternatives:

    • The short-term option would be: get the item price before and after purchasing to make sure there’s no price change after purchasing.
    • Wait for the ProcessReceipt GameEngine API and we will include the purchase price in the receipt. So the dev can check the price directly instead of relying on the update time. We strongly recommend this solution because t-shirt prices would become dynamic in the near future. This is more reliable for the long term. However the dev would need to wait for its release in Nov.

Thank you.

2 Likes

Unfortunately “wait until November” isn’t a viable option for games like PLS DONATE where we have had to disable clothing purchases entirely until this issue is fixed. Player-to-player donations made via clothing purchases makes up a significant portion of donations and this breaking change means a serious loss of revenue. Checking the price alone before and after purchasing does not ensure the price has not changed in that time and fails to stop even primitive exploits.

3 Likes

I sent this via PM with @yqzhang but also wanted to add it here:

With gamepasses, the behavior across all API endpoints and GetProductInfo is that the Updated timestamp does update on price change. For example, with this API:
https://apis.roblox.com/game-passes/v1/game-passes/155254899/product-info, the Updated timestamp changes whenever the game pass price is updated.

It makes 0 sense from a developer perspective to have this differing behavior between asset types, where gamepasses reflect price changes but clothing assets don’t. It almost feels like clothing assets are lagging behind in this regard. A unified approach to this across all product types would be much more predictable and developer-friendly, which is why I’m confused why this behavior has been declared intended.

2 Likes

Fwiw the old endpoint (the one that was used on roblox.com/develop) actually did update the timestamp properly on price changes, I believe the fact that the new endpoint(s) don’t do the same is a long-standing bug.

3 Likes

This unfortunately doesn’t work; not only can PromptPurchaseFinished be spoofed to fire whenever an exploiter so desires (since the hook to determine when it should be fired is sent from the client) but it isn’t fired until the user selects ‘Ok’ on the purchase finished dialog; this gives even a normal player an absolute age to update their clothing item back to the original price if they get really lucky with changing the price for the purchase dialog to notice a lower price than our original price check.

Intermittent price checks are not ideal either as players can still get really lucky with avoiding them or more likely, exploiters just use automated tools to do this cheat for them. This is Robux we are talking about, there’s a large-will for trying to break this sort of system given it’s sensitivity and we as donation game developers have basically been told ‘trust the client for now’; that just isn’t a viable option.

3 Likes

Marking this as solution because it seems like we’re being ignored here. Disappointing from the team responsible.

Followed up with another engineer to see if I can get a closer ETA on the release of ProcessReceipt for avatar items.