Skip to content

fix: strip directory entries and 0-byte files from representations at deploy time#3393

Open
decentraland-bot wants to merge 1 commit intomasterfrom
fix/3388-strip-dir-and-empty-from-representations
Open

fix: strip directory entries and 0-byte files from representations at deploy time#3393
decentraland-bot wants to merge 1 commit intomasterfrom
fix/3388-strip-dir-and-empty-from-representations

Conversation

@decentraland-bot
Copy link
Copy Markdown

Summary

  • In buildItemEntity, after makeContentFiles produces the entity content map, filter each representation's contents array to only include files that are actually in the content map
  • This defensive fix covers items already stored with directory entries (e.g. male/bin/) or 0-byte files (e.g. male/main.crdt) in representations[].contents from older builder-client versions

Root Cause

makeContentFiles (in contentUtils.ts) intentionally skips 0-byte blobs when building the entity content payload:

const isEmpty = files[fileName] instanceof Blob && files[fileName].size === 0
if (FILE_NAME_BLACKLIST.includes(fileName) || isEmpty) continue

However, buildWearableEntityMetadata copies item.data.representations as-is, without applying the same filter. This creates a mismatch: the Catalyst content-validator sees files listed in representation.contents that are absent from the entity content, and rejects the deploy with:

Deploy failed with status 400: Representation content: 'male/bin/' is not one of the content files

Removing the failing entry just moves the error to the next 0-byte or directory entry.

Fix

In buildItemEntity, after makeContentFiles completes, build the set of valid content files and strip any entries in representations[].contents that are not in that set:

const validFiles = new Set(files.keys())
metadata = {
  ...wearableMetadata,
  data: {
    ...wearableMetadata.data,
    representations: wearableMetadata.data.representations.map(rep => ({
      ...rep,
      contents: rep.contents.filter(f => validFiles.has(f))
    }))
  }
}

Changes

  • src/modules/item/export.ts: filter representations[].contents in buildItemEntity to match the actual entity content payload

Why this is needed even after fixing builder-client

The upstream fix in decentraland/builder-client (PR #80) prevents directory entries and 0-byte files from being stored in new items going forward. But items already stored in the Builder API with these entries in their representations[].contents will continue to fail on every curator deploy without this defensive fix.

Closes

#3388


🤖 Created via Slack with Claude
Requested by Rocío Corral Mena via Slack

… deploy time

makeContentFiles already drops 0-byte blobs from the entity content
payload, but buildWearableEntityMetadata copies item.data.representations
as-is. This leaves directory entries (e.g. male/bin/) and 0-byte files
(e.g. male/main.crdt) in the metadata while they are absent from the
content — causing Catalyst to reject the entity with a 400 error.

Filter representations[].contents in buildItemEntity after makeContentFiles
runs, keeping only files that are present in the final entity content map.
This is a defensive fix that covers items already stored with bad data
from older builder-client versions.

Closes #3388
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
builder Error Error Apr 23, 2026 4:33pm

Request Review

@coveralls
Copy link
Copy Markdown

Coverage Report for CI Build 24846819893

Coverage decreased (-0.02%) to 49.792%

Details

  • Coverage decreased (-0.02%) from the base build.
  • Patch coverage: 6 uncovered changes across 1 file (0 of 6 lines covered, 0.0%).
  • 1 coverage regression across 1 file.

Uncovered Changes

File Changed Covered %
src/modules/item/export.ts 6 0 0.0%

Coverage Regressions

1 previously-covered line in 1 file lost coverage.

File Lines Losing Coverage Coverage
src/modules/item/export.ts 1 11.18%

Coverage Stats

Coverage Status
Relevant Lines: 12097
Covered Lines: 6656
Line Coverage: 55.02%
Relevant Branches: 5209
Covered Branches: 1961
Branch Coverage: 37.65%
Branches in Coverage %: Yes
Coverage Strength: 31.54 hits per line

💛 - Coveralls

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants