Describe the bug
Since v3.6, AssetService.createFromFileStream() fails with a NOT NULL constraint violation on asset_translation.languageCode when called without an explicit RequestContext. The method internally calls createAssetInternal() without passing a translations parameter. The fallback in createAssetInternal creates a default translation using ctx.languageCode, but when no RequestContext is provided, RequestContext.empty() is used, which has languageCode: undefined because it creates new Channel() with no defaultLanguageCode.
To Reproduce
// In a plugin service (e.g., generating a sitemap file as an asset)
const stream = new Readable({ encoding: 'utf-8' });
stream.push('sitemap content');
stream.push(null);
// This worked pre-v3.6, fails in v3.6+ with NOT NULL constraint violation
const asset = await this.assetService.createFromFileStream(stream, 'sitemap.txt');
Error output
[TypeORM] Query error: INSERT INTO "asset_translation"("createdAt", "updatedAt", "languageCode", "name", "baseId", "customFields__fix_relational_custom_fields__")
VALUES (DEFAULT, DEFAULT, DEFAULT, $1, $2, DEFAULT) RETURNING "createdAt", "updatedAt", "id"
-- PARAMETERS: ["sitemap.txt",34130]
{
"severity": "ERROR",
"code": "23502",
"detail": "Failing row contains (2026-04-14 16:57:08.266205, 2026-04-14 16:57:08.266205, null, sitemap.txt, 27762, 34130, null).",
"schema": "public",
"table": "asset_translation",
"column": "languageCode"
}
Note that languageCode is null in the failing row and DEFAULT in the query — the value is never set.
Expected behavior
createFromFileStream should work without requiring an explicit RequestContext, as it did before v3.6. The method should either:
- Accept an optional
translations parameter and forward it to createAssetInternal, or
- Use a sensible default
languageCode (e.g., LanguageCode.en) when ctx.languageCode is undefined, or
- Have
RequestContext.empty() provide a fallback languageCode
Root cause analysis
In asset.service.ts:
|
async createFromFileStream( |
All overloads of
createFromFileStream have an optional
RequestContext parameter.
// Line ~380 - createFromFileStream calls createAssetInternal WITHOUT translations
const result = await this.createAssetInternal(ctx, stream, filename, mimetype);
// ^ can be undefined -> used empty without languageCode
When translations is undefined, createAssetInternal falls back to:
// Lines ~483-491
assetTranslations = [
new AssetTranslation({
languageCode: ctx.languageCode, // undefined when ctx = RequestContext.empty()
name: defaultName,
base: savedAsset,
}),
];
And RequestContext.empty() creates a context with new Channel() which has no defaultLanguageCode, so ctx.languageCode is undefined.
|
static empty(): RequestContext { |
|
return new RequestContext({ |
|
apiType: 'admin', |
|
authorizedAsOwnerOnly: false, |
|
channel: new Channel(), |
|
isAuthorized: true, |
|
}); |
|
} |
Environment
- Vendure version: 3.6.2
- Database: PostgreSQL
Workaround
Pass an explicit RequestContext with a valid languageCode:
const ctx = await this.requestContextService.create({
apiType: 'admin',
languageCode: LanguageCode.en,
});
const asset = await this.assetService.createFromFileStream(stream, 'sitemap.txt', ctx);
... or just use any other valid RequestContext
Describe the bug
Since v3.6,
AssetService.createFromFileStream()fails with a NOT NULL constraint violation onasset_translation.languageCodewhen called without an explicitRequestContext. The method internally callscreateAssetInternal()without passing atranslationsparameter. The fallback increateAssetInternalcreates a default translation usingctx.languageCode, but when noRequestContextis provided,RequestContext.empty()is used, which haslanguageCode: undefinedbecause it createsnew Channel()with nodefaultLanguageCode.To Reproduce
Error output
Note that
languageCodeisnullin the failing row andDEFAULTin the query — the value is never set.Expected behavior
createFromFileStreamshould work without requiring an explicitRequestContext, as it did before v3.6. The method should either:translationsparameter and forward it tocreateAssetInternal, orlanguageCode(e.g.,LanguageCode.en) whenctx.languageCodeis undefined, orRequestContext.empty()provide a fallbacklanguageCodeRoot cause analysis
In
asset.service.ts:vendure/packages/core/src/service/services/asset.service.ts
Line 488 in 88467a2
All overloads of
createFromFileStreamhave an optionalRequestContextparameter.When
translationsis undefined,createAssetInternalfalls back to:And
RequestContext.empty()creates a context withnew Channel()which has nodefaultLanguageCode, soctx.languageCodeisundefined.vendure/packages/core/src/api/common/request-context.ts
Lines 225 to 232 in 88467a2
Environment
Workaround
Pass an explicit
RequestContextwith a validlanguageCode:... or just use any other valid
RequestContext