next-intl Error: INVALID_MESSAGE: Missing defaultMessage
Fixes the next-intl build error INVALID_MESSAGE caused by a useTranslations call with no defaultMessage and no matching key. Define the message in your locale files or pass a fallback. Use when the build fails naming INVALID_MESSAGE. Not for runtime missing-key warnings.
next-intl Error: INVALID_MESSAGE: Missing defaultMessage
TL;DR
Fixes the next-intl build error INVALIDMESSAGE caused by a useTranslations call with no defaultMessage and no matching key. Define the message in your locale files or pass a fallback. Use when the build fails naming INVALIDMESSAGE. Not for runtime missing-key warnings.
The error
Error: INVALID_MESSAGE: Missing `defaultMessage` for key `checkout.submit` in locale `en`.Fix it
Step 1: Locate the offending translation call
grep -rn "checkout.submit" src app | head -10Expected: You find the component calling useTranslations with that key.
Step 2: Add the message to your locale files
node -e "console.log('add checkout.submit to messages/en.json and every other locale')"Expected: The key exists in the messages source of truth.
Step 3: Rebuild the project
npm run buildExpected: The build passes with no INVALID_MESSAGE error.
When to use this
- The next-intl build fails with INVALID_MESSAGE
- A key is used in code but absent from every locale file
When NOT to use this
- The app runs but shows the wrong text, that is a message content issue
- The error names a locale mismatch instead, check your locale routing
Tool and version compatibility
- next-intl 3.x
- App Router with next-intl/plugin
Variant phrasings
error in development only
Dev mode tolerates missing messages; the build does not. Fix before shipping.
many INVALID_MESSAGE errors at once
The messages file failed to merge. Check for JSON syntax errors before editing keys.
Why it happens
next-intl validates at build time that every translated key resolves to a message. A component referencing a key that exists nowhere produces INVALID_MESSAGE because the compiler cannot generate a fallback for it.
Edge cases
- Namespace keys like 'a.b.c' fail if an intermediate level is a string, not an object
- Locale files merged from multiple sources can silently drop keys on conflict
- Type-safe keys via createTranslator still error if the JSON is stale
Provenance
Resolved from the public thread: https://vectle.com/posts/pst3k6F2mfbjA-nNkav7TOcQ