decentraland / decentraland/builder
Strip directory entries and 0-byte files from representations[].contents at deploy time
- Dominant language
- TypeScript
- Stars
- 156
- Forks
- 91
- Avg merge
- 2d 7h
- Merged PRs (30d)
- 31
Description
## Problem
When a curator deploys a wearable collection, the Catalyst content-validator rejects the entity with:
```
Deploy failed with status 400: Representation content: 'male/bin/' is not one of the content files
```
This happens because `item.data.representations[].contents` may contain:
- **Directory entries** (e.g. `male/bin/`) — introduced by the zip parser in `builder-client`
- **0-byte files** — silently dropped from the entity content payload by `makeContentFiles` in `src/modules/deployment/contentUtils.ts`, but still listed in the metadata
The metadata and the content payload fall out of sync, and the Catalyst validator catches the mismatch on every deploy attempt.
## Root cause
In `src/modules/deployment/contentUtils.ts`, `makeContentFiles` intentionally skips 0-byte blobs:
```ts
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 means any file skipped by `makeContentFiles` is still present in the entity metadata — causing the Catalyst validator to reject the deploy.
## Proposed fix
In `buildItemEntityBlobs` (or `buildItemEntity`), strip directory entries and 0-byte entries from `representations[].contents` before building the entity metadata:
```ts
const filteredRepresentations = representations.map(rep => ({
...rep,
contents: rep.contents.filter(name => {
if (name.endsWith('/')) return false // skip directory entries
const blob = contentFiles[name]
if (blob instanceof Blob && blob.size === 0) return false // skip 0-byte
return true
})
}))
```
This ensures the metadata passed to `buildEntity` stays in sync with the content payload, regardless of what is stored in the Builder API.
## Why this fix is needed even after fixing builder-client
The upstream fix in `decentraland/builder-client` (filtering at zip extraction time) will prevent new items from being stored with bad data. But items *already stored* in the Builder API with directory entries or 0-byte entries in their `representations[].contents` will continue to fail on deploy without this defensive fix.
## Related
- Upstream fix: decentraland/builder-client#79
Requested by Rocío Corral Mena via Slack
Contributor guide
Assessment
This issue has not been assessed yet.