How to Fix: parser.js from next-config-eslint is missing metadata
The bug is not in your ESLint ruleset—it is in the parser wrapper. The parser.js file in eslint-config-next re-exports the underlying parser but fails to forward its metadata, which breaks consumers that expect parser capabilities and identification fields to be present.
In the affected file, the package exposes parser behavior through a thin proxy. That works for parse or parseForESLint, but newer ESLint integrations and tooling may also inspect exported metadata fields such as parser name, version, or capability descriptors. If those properties are not forwarded, the parser appears incomplete even though parsing itself still works in simpler setups.
Understanding the Root Cause
The underlying issue comes from how CommonJS module exports are assigned in packages/eslint-config-next/parser.js. A minimal wrapper often looks like this:
const babelEslintParser = require('./some-parser')
module.exports = {
parse: babelEslintParser.parse,
parseForESLint: babelEslintParser.parseForESLint,
}
This pattern copies only selected functions. If the real parser also exports meta, name, version, or other fields used by ESLint or editor integrations, they are silently dropped.
That becomes a problem because some tooling does more than call parseForESLint(). It may inspect parser exports to determine:
- whether the parser supports certain ESLint features,
- how to label the parser in diagnostics,
- whether parser services should be enabled,
- or whether compatibility checks should pass.
So the root cause is simple: the wrapper is not a full re-export. It is a partial object copy that omits parser metadata.
Step-by-Step Solution
The safest fix is to export the original parser object directly, or explicitly merge and preserve all of its properties.
Option 1: Re-export the parser directly
If parser.js is only intended to point to the actual parser, this is the cleanest fix:
// packages/eslint-config-next/parser.js
module.exports = require('./parser-bundle')
Replace './parser-bundle' with the actual parser module used inside the package.
This ensures every property from the underlying parser is preserved, including metadata.
Option 2: Spread the parser object and preserve existing exports
If the wrapper needs to augment or override behavior, merge the original parser exports instead of selecting only parse methods:
const parser = require('./parser-bundle')
module.exports = {
...parser,
parse: parser.parse,
parseForESLint: parser.parseForESLint,
}
This keeps metadata like meta intact while still allowing overrides.
Option 3: Explicitly forward metadata
If object spreading is not preferred, forward the missing fields directly:
const parser = require('./parser-bundle')
module.exports = {
parse: parser.parse,
parseForESLint: parser.parseForESLint,
meta: parser.meta,
name: parser.name,
version: parser.version,
}
This works, but it is more brittle because new upstream fields may be added later and missed again.
Recommended patch for this issue
For a maintainable fix in next-config-eslint, prefer a full export pass-through:
// packages/eslint-config-next/parser.js
const parser = require('./parser-bundle')
module.exports = parser
If the current file must remain a wrapper, use:
const parser = require('./parser-bundle')
module.exports = {
...parser,
}
How to verify the fix
After patching, compare the wrapper exports with the original parser:
const wrapped = require('eslint-config-next/parser')
const original = require('./path-to-real-parser')
console.log(Object.keys(wrapped))
console.log(Object.keys(original))
console.log(wrapped.meta)
You should confirm that:
parseexists,parseForESLintexists,metaor equivalent metadata exists,- the wrapper no longer exposes fewer properties than the original parser.
Example pull request summary
If you are contributing the fix upstream, a concise change summary could be:
Fix eslint-config-next parser wrapper to preserve parser metadata.
The existing parser.js only re-exported parse methods, which omitted
metadata from the underlying parser export. Some ESLint consumers inspect
parser metadata directly, so the wrapper should forward the full parser
object instead of a partial subset.
Common Edge Cases
1. The underlying parser export is a function with attached properties
Some parser modules export a callable function and attach meta or helper fields to it. In those cases, reconstructing a new plain object can change behavior. Directly assigning module.exports = parser is safer than rebuilding exports manually.
2. ESM and CommonJS interop issues
If the underlying parser is an ES module transpiled for CommonJS, metadata may live on default:
const parserModule = require('./parser-bundle')
const parser = parserModule.default || parserModule
module.exports = parser
Without this check, you may re-export the wrong layer of the module.
3. Hidden non-enumerable properties
If metadata is defined as a non-enumerable property, using object spread may still miss it. In that case, direct export is better than cloning:
module.exports = require('./parser-bundle')
4. Version mismatches across ESLint packages
Even after fixing metadata forwarding, incompatible versions of ESLint, @typescript-eslint/parser, or Next.js can still produce parser-related errors. Verify your dependency graph before assuming the wrapper fix is the only issue.
5. Tests only cover parsing, not metadata
This bug often slips through because existing tests validate syntax parsing but do not assert parser export shape. Add regression coverage that checks for metadata presence.
it('forwards parser metadata', () => {
const parser = require('../parser')
expect(parser.meta).toBeDefined()
})
FAQ
Why does ESLint care about parser metadata if parsing still works?
Because modern ESLint integrations may inspect the parser object for feature support, identification, or compatibility hints. Parsing alone is not always the full contract.
Is copying parse and parseForESLint not enough?
No. It is enough only for the narrowest use case. If the original parser exposes meta or other fields, those should also be preserved to maintain API compatibility.
What is the best long-term fix for this file?
The best fix is to re-export the underlying parser directly rather than wrapping and selectively copying fields. That avoids future breakage when upstream parser exports change.
If you are patching the issue in the affected parser.js file, the most robust implementation is to stop manually mirroring parser methods and instead forward the complete parser module. That keeps metadata, reduces maintenance overhead, and matches the behavior expected by ESLint consumers.