Skip to content

Commit 7e2e7ed

Browse files
authored
Merge pull request #7142 from NomicFoundation/transform-error
chore: improved the config syntax error message
2 parents 3bd8481 + 9a27cb6 commit 7e2e7ed

File tree

3 files changed

+60
-17
lines changed

3 files changed

+60
-17
lines changed

.changeset/sour-crews-tan.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
"@nomicfoundation/hardhat-errors": patch
3+
"hardhat": patch
4+
---
5+
6+
Improve the error message for syntax errors found in the Hardhat config file ([#7056](https://github.com/NomicFoundation/hardhat/issues/7056))

v-next/hardhat-errors/src/descriptors.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,15 @@ Please add the property "type" with the value "module" in your package.json to e
456456
457457
A fully qualified name should look like file.sol:Contract`,
458458
},
459+
INVALID_CONFIG_FILE: {
460+
number: 21,
461+
messageTemplate: `Invalid Hardhat config file at {configPath}:
462+
{errors}`,
463+
websiteTitle: "Invalid Hardhat config file",
464+
websiteDescription: `The config file has JS/TS errors.
465+
466+
Please resolve the errors before rerunning the command.`,
467+
},
459468
},
460469
INTERNAL: {
461470
ASSERTION_ERROR: {

v-next/hardhat/src/internal/config-loading.ts

Lines changed: 45 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { HardhatUserConfig } from "../types/config.js";
22

3+
import path from "node:path";
34
import { fileURLToPath, pathToFileURL } from "node:url";
45

56
import { HardhatError } from "@nomicfoundation/hardhat-errors";
@@ -140,29 +141,56 @@ async function normalizeConfigPath(configPath: string): Promise<string> {
140141
*/
141142
async function importConfigFileWithTsxFallback(configPath: string) {
142143
try {
143-
return await import(configPath);
144-
} catch (error) {
145-
ensureError(error);
144+
try {
145+
return await import(configPath);
146+
} catch (error) {
147+
ensureError(error);
146148

147-
if (
148-
"code" in error &&
149-
error.code === "ERR_UNKNOWN_FILE_EXTENSION" &&
150-
configPath.endsWith(".ts")
151-
) {
152-
const realPath = await getRealPath(fileURLToPath(configPath));
149+
if (
150+
"code" in error &&
151+
error.code === "ERR_UNKNOWN_FILE_EXTENSION" &&
152+
configPath.endsWith(".ts")
153+
) {
154+
const realPath = await getRealPath(fileURLToPath(configPath));
153155

154-
if (compiledConfigFile.has(realPath)) {
155-
return compiledConfigFile.get(realPath);
156-
}
156+
if (compiledConfigFile.has(realPath)) {
157+
return compiledConfigFile.get(realPath);
158+
}
159+
160+
const { tsImport } = await import("tsx/esm/api");
161+
const config = await tsImport(configPath, import.meta.url);
157162

158-
const { tsImport } = await import("tsx/esm/api");
159-
const config = tsImport(configPath, import.meta.url);
163+
compiledConfigFile.set(realPath, config);
160164

161-
compiledConfigFile.set(realPath, config);
165+
return config;
166+
}
162167

163-
return config;
168+
throw error;
164169
}
170+
} catch (error) {
171+
ensureError(error);
165172

166-
throw error;
173+
switch (error.name) {
174+
case "TransformError":
175+
const errors = error.message
176+
.split("\n")
177+
.filter((line) => line.includes(path.basename(configPath)))
178+
// For example: /.../hardhat.config.ts:86:5: ERROR: Expected "}" but found "\"community-plugin\""
179+
.map((line) => line.split(":"))
180+
.map(
181+
([_path, line, _char, _code, ...message]) =>
182+
`* Syntax error in line ${line}: ${message.join(":").trim()}`,
183+
);
184+
185+
throw new HardhatError(
186+
HardhatError.ERRORS.CORE.GENERAL.INVALID_CONFIG_FILE,
187+
{
188+
configPath,
189+
errors: `\t${errors.join("\n\t")}`,
190+
},
191+
);
192+
default:
193+
throw error;
194+
}
167195
}
168196
}

0 commit comments

Comments
 (0)