Keywords: Node.js | JSON module import | import assertions
Abstract: This article provides an in-depth analysis of the ERR_IMPORT_ASSERTION_TYPE_MISSING error in Node.js 17 and later versions, which stems from changes in JSON module import specifications. It explains the background of the import assertions proposal, compares the differences between assert and with keywords, and demonstrates correct JSON file imports through practical code examples. The article also examines the evolution of Node.js module systems, offering compatibility recommendations and best practices to help developers smoothly handle JSON module imports in TypeScript and JavaScript projects.
Error Phenomenon and Context Analysis
In Node.js 17 and later versions, developers may encounter the following error:
TypeError [ERR_IMPORT_ASSERTION_TYPE_MISSING]:
Module "file:///path/to/countries.json"
needs an import assertion of type "json"
This error typically occurs when attempting to directly import JSON files, such as:
import countryTable from './data/countries.json';
The core cause is Node.js's changed security requirements for JSON module imports. In earlier versions, the --experimental-json-modules flag enabled JSON module support, but starting from Node.js 17, explicit import assertions are required to ensure type safety.
TC39 Proposal and Specification Evolution
This change originates from TC39's import assertions proposal, which aims to add metadata declaration mechanisms to module imports. The proposal initially used the assert keyword but later evolved to use with, while maintaining backward compatibility with assert.
The core idea is: when importing non-JavaScript modules, explicit type declarations are needed to prevent security vulnerabilities and type confusion. For JSON files, type: "json" must be declared to ensure proper file content parsing.
Solution Implementation
According to the proposal specification, there are two correct ways to import JSON:
Using assert Keyword (Compatibility Approach)
import countryTable from "./data/countries.json" assert { type: "json" };
This syntax works in Node.js 17+ and maintains compatibility with earlier proposal versions. The object after assert must contain type: "json", otherwise ERR_IMPORT_ASSERTION_TYPE_MISSING error occurs.
Using with Keyword (Latest Specification)
import countryTable from "./data/countries.json" with { type: "json" };
This is the proposal's latest syntax, where with replaces assert with identical semantics. Recommended for new projects as it represents the future direction of the standard.
Handling in TypeScript Projects
In TypeScript projects, ensure proper tsconfig.json configuration:
{
"compilerOptions": {
"module": "esnext",
"moduleResolution": "node",
"resolveJsonModule": true
}
}
TypeScript 4.5+ supports import assertions syntax. For older versions, transpilation via Babel or esbuild may be necessary.
Node.js Startup Configuration
Before Node.js 17, JSON modules required experimental flag:
node --experimental-json-modules server.js
From Node.js 17 onward, import assertions are required even with this flag. In Node.js 18+, JSON modules are stable and no longer need experimental flags, but import assertions remain necessary.
Practical Application Example
Here's a complete example demonstrating correct JSON import and usage in an API server:
// api.ts
import countryTable from "./data/countries.json" with { type: "json" };
export function getCountryData(code: string) {
return countryTable.find(country => country.code === code);
}
// server.ts
import express from 'express';
import { getCountryData } from './api';
const app = express();
app.get('/country/:code', (req, res) => {
const data = getCountryData(req.params.code);
res.json(data || { error: 'Country not found' });
});
app.listen(3000, () => {
console.log('Server running on port 3000');
});
Compatibility Considerations and Migration Strategy
For projects requiring multi-version Node.js support, consider these strategies:
- Specify Node.js version requirements in package.json:
"engines": { "node": ">=17.0.0" } - Use conditional imports or build-time replacements for syntax differences across environments
- Consider converting JSON data to TypeScript modules to avoid runtime import overhead
Security and Best Practices
Import assertions not only solve JSON import issues but also provide extension mechanisms for other module types (like WebAssembly, CSS). Developers should:
- Always declare
type: "json"for JSON imports - Avoid dynamic JSON imports unless with strict security validation
- Test compatibility across Node.js versions in CI/CD pipelines
By understanding the root cause of ERR_IMPORT_ASSERTION_TYPE_MISSING, developers can better adapt to Node.js module system evolution and write safer, more compatible code.