Summary
The export serialises _assetIds with asset path strings instead of ObjectIds:
```json
"_assetIds": ["course/en/assets/69fb1739d31d6c07413cf209.svg"]
```
_assetIds is an internal cache populated by ContentModule.computeAssetIds and stored in the DB as ObjectIds (cast in ContentModule.update). It should never appear as paths in exported JSON.
Why it matters
On re-import, ContentModule.insert skips recomputing _assetIds when the field is already populated:
```js
if (!data._assetIds) {
data._assetIds = await this.computeAssetIds(data)
}
```
So the path strings get persisted. On the next build, AdaptFrameworkBuild.loadAssetData calls parseObjectId on each entry and throws INVALID_OBJECTID:
```
parseObjectId (parseObjectId.js:17)
AdaptFrameworkBuild.loadAssetData (AdaptFrameworkBuild.js:331)
```
Reproduction
- Author a course with assets.
- Export it.
- `unzip -p .zip build/course/en/components.json | jq '.[]._assetIds'` — observe path strings.
- Re-import the export.
- Trigger preview/build — fails with
INVALID_OBJECTID.
Root cause (likely)
The export performs asset-path rewriting on content fields for portability. The same rewrite is being applied to _assetIds, or the field is being included verbatim from a doc whose content has already had its asset refs replaced with paths.
Fix
`_assetIds` is a derived cache — it should be stripped from the export entirely. The import-side defence (always recompute) has been added in a separate change, but the export should not be producing the field at all.
Workaround applied in import
`AdaptFrameworkImport.importContentObject` now passes `_assetIds: undefined` so the insert path always recomputes. This protects against existing broken exports too.
Summary
The export serialises
_assetIdswith asset path strings instead of ObjectIds:```json
"_assetIds": ["course/en/assets/69fb1739d31d6c07413cf209.svg"]
```
_assetIdsis an internal cache populated byContentModule.computeAssetIdsand stored in the DB as ObjectIds (cast inContentModule.update). It should never appear as paths in exported JSON.Why it matters
On re-import,
ContentModule.insertskips recomputing_assetIdswhen the field is already populated:```js
if (!data._assetIds) {
data._assetIds = await this.computeAssetIds(data)
}
```
So the path strings get persisted. On the next build,
AdaptFrameworkBuild.loadAssetDatacallsparseObjectIdon each entry and throwsINVALID_OBJECTID:```
parseObjectId (parseObjectId.js:17)
AdaptFrameworkBuild.loadAssetData (AdaptFrameworkBuild.js:331)
```
Reproduction
INVALID_OBJECTID.Root cause (likely)
The export performs asset-path rewriting on content fields for portability. The same rewrite is being applied to
_assetIds, or the field is being included verbatim from a doc whose content has already had its asset refs replaced with paths.Fix
`_assetIds` is a derived cache — it should be stripped from the export entirely. The import-side defence (always recompute) has been added in a separate change, but the export should not be producing the field at all.
Workaround applied in import
`AdaptFrameworkImport.importContentObject` now passes `_assetIds: undefined` so the insert path always recomputes. This protects against existing broken exports too.