parcel-bundler/parcel · error · ThrowableDiagnostic
Invalid Web Extension manifest
Error message
Invalid Web Extension manifest
What it means
Thrown by @parcel/transformer-webextension when manifest.json declares default_locale but the expected localization files are missing. The transformer checks the _locales directory (err='key' if the directory itself is absent) and the messages.json inside the locale subfolder (err='value' if the file is missing). The diagnostic highlights the /default_locale pointer in the manifest.
Source
Thrown at packages/transformers/webextension/src/WebExtensionTransformer.js:61
hmrOptions: ?HMROptions,
) {
const hot = Boolean(hmrOptions);
const fs = asset.fs;
const filePath = asset.filePath;
const assetDir = path.dirname(filePath);
const isMV2 = program.manifest_version == 2;
delete program.$schema;
if (program.default_locale) {
const locales = path.join(assetDir, '_locales');
let err = !(await fs.exists(locales))
? 'key'
: !(await fs.exists(
path.join(locales, program.default_locale, 'messages.json'),
))
? 'value'
: null;
if (err) {
throw new ThrowableDiagnostic({
diagnostic: [
{
message: 'Invalid Web Extension manifest',
origin: '@parcel/transformer-webextension',
codeFrames: [
{
filePath,
codeHighlights: [
{
...getJSONHighlightLocation(ptrs['/default_locale'], err),
message: md`Localization ${
err == 'value'
? 'file for ' + program.default_locale
: 'directory'
} does not exist: ${path.relative(
assetDir,
path.join(locales, program.default_locale),
)}`,View on GitHub (pinned to 59484858a1)
Solutions
- Create _locales/<default_locale>/messages.json relative to manifest.json.
- Ensure the locale code in default_locale exactly matches the subdirectory name.
- Remove the default_locale field if the extension has no internationalization.
Example fix
// before
{ "default_locale": "en" } // no _locales/en/messages.json
// after
create file: _locales/en/messages.json with { "msg": { "message": "..." } } Defensive patterns
Strategy: validation
Validate before calling
const fs = require('fs').promises;
const path = require('path');
if (manifest.default_locale) {
const dir = path.join(assetDir, '_locales', manifest.default_locale);
const file = path.join(dir, 'messages.json');
await fs.access(dir).catch(() => { throw new Error('Missing _locales/' + manifest.default_locale); });
await fs.access(file).catch(() => { throw new Error('Missing messages.json for ' + manifest.default_locale); });
} Prevention
- Always create _locales/<locale>/messages.json when setting default_locale.
- Keep the locale code consistent across default_locale and the folder name.
- Drop default_locale if the extension is not internationalized.
When it happens
Trigger: collectDependencies runs with program.default_locale truthy; fs.exists(assetDir/_locales) is false (key error) OR fs.exists(assetDir/_locales/<default_locale>/messages.json) is false (value error).
Common situations: Manifest sets "default_locale": "en" but the _locales directory was never created, the locale code is wrong (en vs en_US), or messages.json was renamed/moved out of the locale folder.
Related errors
- [dynamic diagnostic from SVG transform errors]
- [dynamic diagnostic from TypeScript compiler errors]
- Vue config should be an object.
- [dynamic diagnostic from Vue compiler parse errors]
- Unknown template language: "${template.lang}"
AI-assisted analysis of parcel-bundler/parcel@59484858a1 (2026-08-13).
Data as JSON: /api/errors/1682f8223067c5b7.
Report an issue: GitHub.