Skip to main content

node_resolver/
errors.rs

1// Copyright 2018-2026 the Deno authors. MIT license.
2
3use std::borrow::Cow;
4use std::fmt::Write;
5use std::path::PathBuf;
6
7use boxed_error::Boxed;
8use deno_error::JsError;
9use deno_package_json::MissingPkgJsonNameError;
10use deno_path_util::UrlToFilePathError;
11use thiserror::Error;
12use url::Url;
13
14use crate::NodeResolutionKind;
15use crate::ResolutionMode;
16use crate::path::UrlOrPath;
17
18#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
19#[allow(non_camel_case_types)]
20pub enum NodeJsErrorCode {
21  ERR_INVALID_MODULE_SPECIFIER,
22  ERR_INVALID_PACKAGE_CONFIG,
23  ERR_INVALID_PACKAGE_TARGET,
24  ERR_MODULE_NOT_FOUND,
25  ERR_PACKAGE_IMPORT_NOT_DEFINED,
26  ERR_PACKAGE_PATH_NOT_EXPORTED,
27  ERR_UNKNOWN_FILE_EXTENSION,
28  ERR_UNSUPPORTED_DIR_IMPORT,
29  ERR_UNSUPPORTED_ESM_URL_SCHEME,
30  ERR_INVALID_FILE_URL_PATH,
31  ERR_UNKNOWN_BUILTIN_MODULE,
32  /// Deno specific since Node doesn't support type checking TypeScript.
33  ERR_TYPES_NOT_FOUND,
34}
35
36impl std::fmt::Display for NodeJsErrorCode {
37  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
38    write!(f, "{}", self.as_str())
39  }
40}
41
42impl NodeJsErrorCode {
43  pub fn as_str(&self) -> &'static str {
44    use NodeJsErrorCode::*;
45    match self {
46      ERR_INVALID_MODULE_SPECIFIER => "ERR_INVALID_MODULE_SPECIFIER",
47      ERR_INVALID_PACKAGE_CONFIG => "ERR_INVALID_PACKAGE_CONFIG",
48      ERR_INVALID_PACKAGE_TARGET => "ERR_INVALID_PACKAGE_TARGET",
49      ERR_MODULE_NOT_FOUND => "ERR_MODULE_NOT_FOUND",
50      ERR_PACKAGE_IMPORT_NOT_DEFINED => "ERR_PACKAGE_IMPORT_NOT_DEFINED",
51      ERR_PACKAGE_PATH_NOT_EXPORTED => "ERR_PACKAGE_PATH_NOT_EXPORTED",
52      ERR_UNKNOWN_FILE_EXTENSION => "ERR_UNKNOWN_FILE_EXTENSION",
53      ERR_UNSUPPORTED_DIR_IMPORT => "ERR_UNSUPPORTED_DIR_IMPORT",
54      ERR_UNSUPPORTED_ESM_URL_SCHEME => "ERR_UNSUPPORTED_ESM_URL_SCHEME",
55      ERR_TYPES_NOT_FOUND => "ERR_TYPES_NOT_FOUND",
56      ERR_INVALID_FILE_URL_PATH => "ERR_INVALID_FILE_URL_PATH",
57      ERR_UNKNOWN_BUILTIN_MODULE => "ERR_UNKNOWN_BUILTIN_MODULE",
58    }
59  }
60}
61
62impl From<NodeJsErrorCode> for deno_error::PropertyValue {
63  fn from(value: NodeJsErrorCode) -> Self {
64    deno_error::PropertyValue::String(value.as_str().into())
65  }
66}
67
68pub trait NodeJsErrorCoded {
69  fn code(&self) -> NodeJsErrorCode;
70}
71
72#[derive(Debug, Clone, Error, JsError)]
73#[error(
74  "[{}] Invalid module '{}' {}{}",
75  self.code(),
76  request,
77  reason,
78  maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default()
79)]
80#[class(type)]
81#[property("code" = self.code())]
82pub struct InvalidModuleSpecifierError {
83  pub request: String,
84  pub reason: Cow<'static, str>,
85  pub maybe_referrer: Option<String>,
86}
87
88impl NodeJsErrorCoded for InvalidModuleSpecifierError {
89  fn code(&self) -> NodeJsErrorCode {
90    NodeJsErrorCode::ERR_INVALID_MODULE_SPECIFIER
91  }
92}
93
94#[derive(Debug, Boxed, JsError)]
95pub struct LegacyResolveError(pub Box<LegacyResolveErrorKind>);
96
97impl LegacyResolveError {
98  pub fn specifier(&self) -> &UrlOrPath {
99    match self.as_kind() {
100      LegacyResolveErrorKind::TypesNotFound(err) => &err.0.code_specifier,
101      LegacyResolveErrorKind::ModuleNotFound(err) => &err.specifier,
102    }
103  }
104}
105
106#[derive(Debug, Error, JsError)]
107pub enum LegacyResolveErrorKind {
108  #[class(inherit)]
109  #[error(transparent)]
110  TypesNotFound(#[from] TypesNotFoundError),
111  #[class(inherit)]
112  #[error(transparent)]
113  ModuleNotFound(#[from] ModuleNotFoundError),
114}
115
116impl NodeJsErrorCoded for LegacyResolveError {
117  fn code(&self) -> NodeJsErrorCode {
118    match self.as_kind() {
119      LegacyResolveErrorKind::TypesNotFound(e) => e.code(),
120      LegacyResolveErrorKind::ModuleNotFound(e) => e.code(),
121    }
122  }
123}
124
125#[derive(Debug, Error, JsError)]
126#[error(
127  "Could not find package '{}' from referrer '{}'{}.",
128  package_name,
129  referrer,
130  referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
131)]
132#[class(generic)]
133#[property("code" = self.code())]
134pub struct PackageNotFoundError {
135  pub package_name: String,
136  pub referrer: UrlOrPath,
137  /// Extra information about the referrer.
138  pub referrer_extra: Option<String>,
139}
140
141impl NodeJsErrorCoded for PackageNotFoundError {
142  fn code(&self) -> NodeJsErrorCode {
143    NodeJsErrorCode::ERR_MODULE_NOT_FOUND
144  }
145}
146
147#[derive(Debug, Error, JsError)]
148#[error(
149  "Could not find referrer npm package '{}'{}.",
150  referrer,
151  referrer_extra.as_ref().map(|r| format!(" ({})", r)).unwrap_or_default()
152)]
153#[class(generic)]
154#[property("code" = self.code())]
155pub struct ReferrerNotFoundError {
156  pub referrer: UrlOrPath,
157  /// Extra information about the referrer.
158  pub referrer_extra: Option<String>,
159}
160
161impl NodeJsErrorCoded for ReferrerNotFoundError {
162  fn code(&self) -> NodeJsErrorCode {
163    NodeJsErrorCode::ERR_MODULE_NOT_FOUND
164  }
165}
166
167#[derive(Debug, Error, JsError)]
168#[class(inherit)]
169#[error("Failed resolving '{package_name}' from referrer '{referrer}'.")]
170#[property("code" = self.code())]
171pub struct PackageFolderResolveIoError {
172  pub package_name: String,
173  pub referrer: UrlOrPath,
174  #[source]
175  #[inherit]
176  pub source: std::io::Error,
177}
178
179impl NodeJsErrorCoded for PackageFolderResolveIoError {
180  fn code(&self) -> NodeJsErrorCode {
181    NodeJsErrorCode::ERR_MODULE_NOT_FOUND
182  }
183}
184
185impl NodeJsErrorCoded for PackageFolderResolveErrorKind {
186  fn code(&self) -> NodeJsErrorCode {
187    match self {
188      PackageFolderResolveErrorKind::PackageNotFound(e) => e.code(),
189      PackageFolderResolveErrorKind::ReferrerNotFound(e) => e.code(),
190      PackageFolderResolveErrorKind::Io(e) => e.code(),
191      PackageFolderResolveErrorKind::PathToUrl(_) => {
192        NodeJsErrorCode::ERR_INVALID_FILE_URL_PATH
193      }
194    }
195  }
196}
197
198#[derive(Debug, Boxed, JsError)]
199pub struct PackageFolderResolveError(pub Box<PackageFolderResolveErrorKind>);
200
201#[derive(Debug, Error, JsError)]
202pub enum PackageFolderResolveErrorKind {
203  #[class(inherit)]
204  #[error(transparent)]
205  PackageNotFound(#[from] PackageNotFoundError),
206  #[class(inherit)]
207  #[error(transparent)]
208  ReferrerNotFound(#[from] ReferrerNotFoundError),
209  #[class(inherit)]
210  #[error(transparent)]
211  Io(#[from] PackageFolderResolveIoError),
212  #[class(inherit)]
213  #[error(transparent)]
214  #[property("code" = self.code())]
215  PathToUrl(#[from] deno_path_util::PathToUrlError),
216}
217
218#[derive(Debug, Boxed, JsError)]
219pub struct PackageSubpathFromDenoModuleResolveError(
220  pub Box<PackageSubpathFromDenoModuleResolveErrorKind>,
221);
222
223impl NodeJsErrorCoded for PackageSubpathFromDenoModuleResolveError {
224  fn code(&self) -> NodeJsErrorCode {
225    match self.as_kind() {
226      PackageSubpathFromDenoModuleResolveErrorKind::SubPath(e) => e.code(),
227      PackageSubpathFromDenoModuleResolveErrorKind::FinalizeResolution(e) => {
228        e.code()
229      }
230    }
231  }
232}
233
234impl PackageSubpathFromDenoModuleResolveError {
235  pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
236    match self.as_kind() {
237      PackageSubpathFromDenoModuleResolveErrorKind::SubPath(e) => {
238        e.as_types_not_found()
239      }
240      PackageSubpathFromDenoModuleResolveErrorKind::FinalizeResolution(e) => {
241        e.as_types_not_found()
242      }
243    }
244  }
245
246  pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
247    match self.as_kind() {
248      PackageSubpathFromDenoModuleResolveErrorKind::SubPath(e) => {
249        e.maybe_specifier()
250      }
251      PackageSubpathFromDenoModuleResolveErrorKind::FinalizeResolution(e) => {
252        e.maybe_specifier()
253      }
254    }
255  }
256
257  pub fn into_node_resolve_error(self) -> NodeResolveError {
258    match self.into_kind() {
259      PackageSubpathFromDenoModuleResolveErrorKind::SubPath(e) => {
260        NodeResolveErrorKind::PackageResolve(
261          PackageResolveErrorKind::SubpathResolve(e).into_box(),
262        )
263      }
264      PackageSubpathFromDenoModuleResolveErrorKind::FinalizeResolution(e) => {
265        NodeResolveErrorKind::FinalizeResolution(e)
266      }
267    }
268    .into_box()
269  }
270}
271
272#[derive(Debug, Error, JsError)]
273pub enum PackageSubpathFromDenoModuleResolveErrorKind {
274  #[class(inherit)]
275  #[error(transparent)]
276  SubPath(#[from] PackageSubpathResolveError),
277  #[class(inherit)]
278  #[error(transparent)]
279  FinalizeResolution(#[from] FinalizeResolutionError),
280}
281
282#[derive(Debug, Boxed, JsError)]
283pub struct PackageSubpathResolveError(pub Box<PackageSubpathResolveErrorKind>);
284
285impl NodeJsErrorCoded for PackageSubpathResolveError {
286  fn code(&self) -> NodeJsErrorCode {
287    match self.as_kind() {
288      PackageSubpathResolveErrorKind::PkgJsonLoad(e) => e.code(),
289      PackageSubpathResolveErrorKind::Exports(e) => e.code(),
290      PackageSubpathResolveErrorKind::LegacyResolve(e) => e.code(),
291    }
292  }
293}
294
295impl PackageSubpathResolveError {
296  pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
297    self.as_kind().as_types_not_found()
298  }
299
300  pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
301    match self.as_kind() {
302      PackageSubpathResolveErrorKind::PkgJsonLoad(_) => None,
303      PackageSubpathResolveErrorKind::Exports(err) => err.maybe_specifier(),
304      PackageSubpathResolveErrorKind::LegacyResolve(err) => {
305        Some(Cow::Borrowed(err.specifier()))
306      }
307    }
308  }
309}
310
311#[derive(Debug, Error, JsError)]
312pub enum PackageSubpathResolveErrorKind {
313  #[class(inherit)]
314  #[error(transparent)]
315  PkgJsonLoad(#[from] PackageJsonLoadError),
316  #[class(inherit)]
317  #[error(transparent)]
318  Exports(PackageExportsResolveError),
319  #[class(inherit)]
320  #[error(transparent)]
321  LegacyResolve(LegacyResolveError),
322}
323
324impl PackageSubpathResolveErrorKind {
325  pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
326    match self {
327      PackageSubpathResolveErrorKind::PkgJsonLoad(_) => None,
328      PackageSubpathResolveErrorKind::Exports(err) => match err.as_kind() {
329        PackageExportsResolveErrorKind::PackagePathNotExported(_) => None,
330        PackageExportsResolveErrorKind::PackageTargetResolve(err) => {
331          match err.as_kind() {
332            PackageTargetResolveErrorKind::TypesNotFound(not_found) => {
333              Some(not_found)
334            }
335            PackageTargetResolveErrorKind::NotFound(_)
336            | PackageTargetResolveErrorKind::InvalidPackageTarget(_)
337            | PackageTargetResolveErrorKind::InvalidModuleSpecifier(_)
338            | PackageTargetResolveErrorKind::PackageResolve(_)
339            | PackageTargetResolveErrorKind::UnknownBuiltInNodeModule(_)
340            | PackageTargetResolveErrorKind::UrlToFilePath(_) => None,
341          }
342        }
343      },
344      PackageSubpathResolveErrorKind::LegacyResolve(err) => match err.as_kind()
345      {
346        LegacyResolveErrorKind::TypesNotFound(not_found) => Some(not_found),
347        LegacyResolveErrorKind::ModuleNotFound(_) => None,
348      },
349    }
350  }
351}
352
353#[derive(Debug, Error, JsError)]
354#[class(generic)]
355#[error(
356  "Target '{}' not found from '{}'{}{}.",
357  target,
358  pkg_json_path.display(),
359  maybe_referrer.as_ref().map(|r|
360    format!(
361      " from{} referrer {}",
362      match resolution_mode {
363        ResolutionMode::Import => "",
364        ResolutionMode::Require => " cjs",
365      },
366      r
367    )
368  ).unwrap_or_default(),
369  match resolution_kind {
370    NodeResolutionKind::Execution => "",
371    NodeResolutionKind::Types => " for types",
372  }
373)]
374#[property("code" = self.code())]
375pub struct PackageTargetNotFoundError {
376  pub pkg_json_path: PathBuf,
377  pub target: String,
378  pub maybe_resolved: Option<UrlOrPath>,
379  pub maybe_referrer: Option<UrlOrPath>,
380  pub resolution_mode: ResolutionMode,
381  pub resolution_kind: NodeResolutionKind,
382}
383
384impl NodeJsErrorCoded for PackageTargetNotFoundError {
385  fn code(&self) -> NodeJsErrorCode {
386    NodeJsErrorCode::ERR_MODULE_NOT_FOUND
387  }
388}
389
390impl NodeJsErrorCoded for PackageTargetResolveErrorKind {
391  fn code(&self) -> NodeJsErrorCode {
392    match self {
393      PackageTargetResolveErrorKind::NotFound(e) => e.code(),
394      PackageTargetResolveErrorKind::InvalidPackageTarget(e) => e.code(),
395      PackageTargetResolveErrorKind::InvalidModuleSpecifier(e) => e.code(),
396      PackageTargetResolveErrorKind::PackageResolve(e) => e.code(),
397      PackageTargetResolveErrorKind::TypesNotFound(e) => e.code(),
398      PackageTargetResolveErrorKind::UnknownBuiltInNodeModule(e) => e.code(),
399      PackageTargetResolveErrorKind::UrlToFilePath(_) => {
400        NodeJsErrorCode::ERR_INVALID_FILE_URL_PATH
401      }
402    }
403  }
404}
405
406#[derive(Debug, Boxed, JsError)]
407pub struct PackageTargetResolveError(pub Box<PackageTargetResolveErrorKind>);
408
409impl PackageTargetResolveError {
410  pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
411    match self.as_kind() {
412      PackageTargetResolveErrorKind::NotFound(err) => {
413        err.maybe_resolved.as_ref().map(Cow::Borrowed)
414      }
415      PackageTargetResolveErrorKind::PackageResolve(err) => {
416        err.maybe_specifier()
417      }
418      PackageTargetResolveErrorKind::TypesNotFound(err) => {
419        Some(Cow::Borrowed(&err.0.code_specifier))
420      }
421      PackageTargetResolveErrorKind::UnknownBuiltInNodeModule(err) => {
422        err.maybe_specifier().map(|u| Cow::Owned(UrlOrPath::Url(u)))
423      }
424      PackageTargetResolveErrorKind::UrlToFilePath(e) => {
425        Some(Cow::Owned(UrlOrPath::Url(e.0.clone())))
426      }
427      PackageTargetResolveErrorKind::InvalidPackageTarget(_)
428      | PackageTargetResolveErrorKind::InvalidModuleSpecifier(_) => None,
429    }
430  }
431}
432
433#[derive(Debug, Error, JsError)]
434pub enum PackageTargetResolveErrorKind {
435  #[class(inherit)]
436  #[error(transparent)]
437  NotFound(#[from] PackageTargetNotFoundError),
438  #[class(inherit)]
439  #[error(transparent)]
440  InvalidPackageTarget(#[from] InvalidPackageTargetError),
441  #[class(inherit)]
442  #[error(transparent)]
443  InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
444  #[class(inherit)]
445  #[error(transparent)]
446  PackageResolve(#[from] PackageResolveError),
447  #[class(inherit)]
448  #[error(transparent)]
449  TypesNotFound(#[from] TypesNotFoundError),
450  #[class(inherit)]
451  #[error(transparent)]
452  UnknownBuiltInNodeModule(#[from] UnknownBuiltInNodeModuleError),
453  #[class(inherit)]
454  #[error(transparent)]
455  #[property("code" = self.code())]
456  UrlToFilePath(#[from] deno_path_util::UrlToFilePathError),
457}
458
459impl PackageTargetResolveErrorKind {
460  pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
461    match self {
462      Self::TypesNotFound(not_found) => Some(not_found),
463      _ => None,
464    }
465  }
466}
467
468impl NodeJsErrorCoded for PackageExportsResolveErrorKind {
469  fn code(&self) -> NodeJsErrorCode {
470    match self {
471      PackageExportsResolveErrorKind::PackagePathNotExported(e) => e.code(),
472      PackageExportsResolveErrorKind::PackageTargetResolve(e) => e.code(),
473    }
474  }
475}
476
477#[derive(Debug, Boxed, JsError)]
478pub struct PackageExportsResolveError(pub Box<PackageExportsResolveErrorKind>);
479
480impl PackageExportsResolveError {
481  pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
482    match self.as_kind() {
483      PackageExportsResolveErrorKind::PackagePathNotExported(_) => None,
484      PackageExportsResolveErrorKind::PackageTargetResolve(err) => {
485        err.maybe_specifier()
486      }
487    }
488  }
489}
490
491#[derive(Debug, Error, JsError)]
492pub enum PackageExportsResolveErrorKind {
493  #[class(inherit)]
494  #[error(transparent)]
495  PackagePathNotExported(#[from] PackagePathNotExportedError),
496  #[class(inherit)]
497  #[error(transparent)]
498  PackageTargetResolve(#[from] PackageTargetResolveError),
499}
500
501#[derive(Debug, Error, JsError)]
502#[error(
503    "[{}] Could not find types for '{}'{}",
504    self.code(),
505    self.0.code_specifier,
506    self.0.maybe_referrer.as_ref().map(|r| format!(" imported from '{}'", r)).unwrap_or_default(),
507  )]
508#[class(generic)]
509#[property("code" = self.code())]
510pub struct TypesNotFoundError(pub Box<TypesNotFoundErrorData>);
511
512#[derive(Debug)]
513pub struct TypesNotFoundErrorData {
514  pub code_specifier: UrlOrPath,
515  pub maybe_referrer: Option<UrlOrPath>,
516}
517
518impl NodeJsErrorCoded for TypesNotFoundError {
519  fn code(&self) -> NodeJsErrorCode {
520    NodeJsErrorCode::ERR_TYPES_NOT_FOUND
521  }
522}
523
524#[derive(Debug, Error, JsError)]
525#[class(inherit)]
526#[error("[{}] Invalid package config. {}", self.code(), .0)]
527pub struct PackageJsonLoadError(pub deno_package_json::PackageJsonLoadError);
528
529impl NodeJsErrorCoded for PackageJsonLoadError {
530  fn code(&self) -> NodeJsErrorCode {
531    NodeJsErrorCode::ERR_INVALID_PACKAGE_CONFIG
532  }
533}
534
535#[derive(Debug, Error, JsError)]
536#[class(type)]
537#[error(
538  "[{}] Package import specifier \"{}\" is not defined{}{}",
539  self.code(),
540  name,
541  package_json_path.as_ref().map(|p| format!(" in package {}", p.display())).unwrap_or_default(),
542  maybe_referrer.as_ref().map(|r| format!(" imported from '{}'", r)).unwrap_or_default(),
543)]
544#[property("code" = self.code())]
545pub struct PackageImportNotDefinedError {
546  pub name: String,
547  pub package_json_path: Option<PathBuf>,
548  pub maybe_referrer: Option<UrlOrPath>,
549}
550
551impl NodeJsErrorCoded for PackageImportNotDefinedError {
552  fn code(&self) -> NodeJsErrorCode {
553    NodeJsErrorCode::ERR_PACKAGE_IMPORT_NOT_DEFINED
554  }
555}
556
557#[derive(Debug, Boxed, JsError)]
558pub struct PackageImportsResolveError(pub Box<PackageImportsResolveErrorKind>);
559
560impl PackageImportsResolveError {
561  pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
562    match self.as_kind() {
563      PackageImportsResolveErrorKind::Target(err) => err.maybe_specifier(),
564      PackageImportsResolveErrorKind::PkgJsonLoad(_)
565      | PackageImportsResolveErrorKind::InvalidModuleSpecifier(_)
566      | PackageImportsResolveErrorKind::NotDefined(_) => None,
567    }
568  }
569}
570
571#[derive(Debug, Error, JsError)]
572pub enum PackageImportsResolveErrorKind {
573  #[class(inherit)]
574  #[error(transparent)]
575  PkgJsonLoad(PackageJsonLoadError),
576  #[class(inherit)]
577  #[error(transparent)]
578  InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
579  #[class(inherit)]
580  #[error(transparent)]
581  NotDefined(#[from] PackageImportNotDefinedError),
582  #[class(inherit)]
583  #[error(transparent)]
584  Target(#[from] PackageTargetResolveError),
585}
586
587impl PackageImportsResolveErrorKind {
588  pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
589    match self {
590      Self::Target(err) => err.as_types_not_found(),
591      _ => None,
592    }
593  }
594}
595
596impl NodeJsErrorCoded for PackageImportsResolveErrorKind {
597  fn code(&self) -> NodeJsErrorCode {
598    match self {
599      Self::PkgJsonLoad(e) => e.code(),
600      Self::InvalidModuleSpecifier(e) => e.code(),
601      Self::NotDefined(e) => e.code(),
602      Self::Target(e) => e.code(),
603    }
604  }
605}
606
607impl NodeJsErrorCoded for PackageResolveErrorKind {
608  fn code(&self) -> NodeJsErrorCode {
609    match self {
610      PackageResolveErrorKind::PkgJsonLoad(e) => e.code(),
611      PackageResolveErrorKind::InvalidModuleSpecifier(e) => e.code(),
612      PackageResolveErrorKind::PackageFolderResolve(e) => e.code(),
613      PackageResolveErrorKind::ExportsResolve(e) => e.code(),
614      PackageResolveErrorKind::SubpathResolve(e) => e.code(),
615      PackageResolveErrorKind::UrlToFilePath(_) => {
616        NodeJsErrorCode::ERR_INVALID_FILE_URL_PATH
617      }
618    }
619  }
620}
621
622#[derive(Debug, Boxed, JsError)]
623pub struct PackageResolveError(pub Box<PackageResolveErrorKind>);
624
625impl PackageResolveError {
626  pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
627    match self.as_kind() {
628      PackageResolveErrorKind::ExportsResolve(err) => err.maybe_specifier(),
629      PackageResolveErrorKind::SubpathResolve(err) => err.maybe_specifier(),
630      PackageResolveErrorKind::UrlToFilePath(err) => {
631        Some(Cow::Owned(UrlOrPath::Url(err.0.clone())))
632      }
633      PackageResolveErrorKind::PkgJsonLoad(_)
634      | PackageResolveErrorKind::InvalidModuleSpecifier(_)
635      | PackageResolveErrorKind::PackageFolderResolve(_) => None,
636    }
637  }
638}
639
640#[derive(Debug, Error, JsError)]
641pub enum PackageResolveErrorKind {
642  #[class(inherit)]
643  #[error(transparent)]
644  PkgJsonLoad(#[from] PackageJsonLoadError),
645  #[class(inherit)]
646  #[error(transparent)]
647  InvalidModuleSpecifier(#[from] InvalidModuleSpecifierError),
648  #[class(inherit)]
649  #[error(transparent)]
650  PackageFolderResolve(#[from] PackageFolderResolveError),
651  #[class(inherit)]
652  #[error(transparent)]
653  ExportsResolve(#[from] PackageExportsResolveError),
654  #[class(inherit)]
655  #[error(transparent)]
656  SubpathResolve(#[from] PackageSubpathResolveError),
657  #[class(inherit)]
658  #[error(transparent)]
659  #[property("code" = self.code())]
660  UrlToFilePath(#[from] UrlToFilePathError),
661}
662
663impl PackageResolveErrorKind {
664  pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
665    match self {
666      PackageResolveErrorKind::PkgJsonLoad(_)
667      | PackageResolveErrorKind::InvalidModuleSpecifier(_)
668      | PackageResolveErrorKind::PackageFolderResolve(_)
669      | PackageResolveErrorKind::ExportsResolve(_)
670      | PackageResolveErrorKind::UrlToFilePath(_) => None,
671      PackageResolveErrorKind::SubpathResolve(err) => err.as_types_not_found(),
672    }
673  }
674}
675
676#[derive(Debug, Error, JsError)]
677#[class(generic)]
678#[error("Failed joining '{path}' from '{base}'.")]
679pub struct NodeResolveRelativeJoinError {
680  pub path: String,
681  pub base: Url,
682  #[source]
683  pub source: url::ParseError,
684}
685
686#[derive(Debug, Error, JsError)]
687#[class(generic)]
688#[error("Failed resolving specifier from data url referrer.")]
689pub struct DataUrlReferrerError {
690  #[source]
691  pub source: url::ParseError,
692}
693
694#[derive(Debug, Boxed, JsError)]
695pub struct NodeResolveError(pub Box<NodeResolveErrorKind>);
696
697impl NodeResolveError {
698  pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
699    match self.as_kind() {
700      NodeResolveErrorKind::PathToUrl(err) => {
701        Some(Cow::Owned(UrlOrPath::Path(err.0.clone())))
702      }
703      NodeResolveErrorKind::UrlToFilePath(err) => {
704        Some(Cow::Owned(UrlOrPath::Url(err.0.clone())))
705      }
706      NodeResolveErrorKind::PackageImportsResolve(err) => err.maybe_specifier(),
707      NodeResolveErrorKind::PackageResolve(err) => err.maybe_specifier(),
708      NodeResolveErrorKind::TypesNotFound(err) => {
709        Some(Cow::Borrowed(&err.0.code_specifier))
710      }
711      NodeResolveErrorKind::UnknownBuiltInNodeModule(err) => {
712        err.maybe_specifier().map(|u| Cow::Owned(UrlOrPath::Url(u)))
713      }
714      NodeResolveErrorKind::FinalizeResolution(err) => err.maybe_specifier(),
715      NodeResolveErrorKind::UnsupportedEsmUrlScheme(_)
716      | NodeResolveErrorKind::DataUrlReferrer(_)
717      | NodeResolveErrorKind::RelativeJoin(_) => None,
718    }
719  }
720}
721
722#[derive(Debug, Error, JsError)]
723pub enum NodeResolveErrorKind {
724  #[class(inherit)]
725  #[error(transparent)]
726  RelativeJoin(#[from] NodeResolveRelativeJoinError),
727  #[class(inherit)]
728  #[error(transparent)]
729  PathToUrl(#[from] deno_path_util::PathToUrlError),
730  #[class(inherit)]
731  #[error(transparent)]
732  UrlToFilePath(#[from] deno_path_util::UrlToFilePathError),
733  #[class(inherit)]
734  #[error(transparent)]
735  PackageImportsResolve(#[from] PackageImportsResolveError),
736  #[class(inherit)]
737  #[error(transparent)]
738  UnsupportedEsmUrlScheme(#[from] UnsupportedEsmUrlSchemeError),
739  #[class(inherit)]
740  #[error(transparent)]
741  DataUrlReferrer(#[from] DataUrlReferrerError),
742  #[class(inherit)]
743  #[error(transparent)]
744  PackageResolve(#[from] PackageResolveError),
745  #[class(inherit)]
746  #[error(transparent)]
747  TypesNotFound(#[from] TypesNotFoundError),
748  #[class(inherit)]
749  #[error(transparent)]
750  UnknownBuiltInNodeModule(#[from] UnknownBuiltInNodeModuleError),
751  #[class(inherit)]
752  #[error(transparent)]
753  FinalizeResolution(#[from] FinalizeResolutionError),
754}
755
756impl NodeResolveErrorKind {
757  pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
758    match self {
759      NodeResolveErrorKind::TypesNotFound(not_found) => Some(not_found),
760      NodeResolveErrorKind::PackageImportsResolve(err) => {
761        err.as_kind().as_types_not_found()
762      }
763      NodeResolveErrorKind::PackageResolve(package_resolve_error) => {
764        package_resolve_error.as_types_not_found()
765      }
766      NodeResolveErrorKind::UnsupportedEsmUrlScheme(_)
767      | NodeResolveErrorKind::DataUrlReferrer(_)
768      | NodeResolveErrorKind::FinalizeResolution(_)
769      | NodeResolveErrorKind::RelativeJoin(_)
770      | NodeResolveErrorKind::PathToUrl(_)
771      | NodeResolveErrorKind::UnknownBuiltInNodeModule(_)
772      | NodeResolveErrorKind::UrlToFilePath(_) => None,
773    }
774  }
775
776  pub fn maybe_code(&self) -> Option<NodeJsErrorCode> {
777    match self {
778      NodeResolveErrorKind::RelativeJoin(_) => None,
779      NodeResolveErrorKind::PathToUrl(_) => None,
780      NodeResolveErrorKind::UrlToFilePath(_) => None,
781      NodeResolveErrorKind::PackageImportsResolve(e) => Some(e.code()),
782      NodeResolveErrorKind::UnsupportedEsmUrlScheme(e) => Some(e.code()),
783      NodeResolveErrorKind::DataUrlReferrer(_) => None,
784      NodeResolveErrorKind::PackageResolve(e) => Some(e.code()),
785      NodeResolveErrorKind::TypesNotFound(e) => Some(e.code()),
786      NodeResolveErrorKind::UnknownBuiltInNodeModule(e) => Some(e.code()),
787      NodeResolveErrorKind::FinalizeResolution(e) => Some(e.code()),
788    }
789  }
790}
791
792#[derive(Debug, Boxed, JsError)]
793pub struct FinalizeResolutionError(pub Box<FinalizeResolutionErrorKind>);
794
795impl FinalizeResolutionError {
796  pub fn maybe_specifier(&self) -> Option<Cow<'_, UrlOrPath>> {
797    match self.as_kind() {
798      FinalizeResolutionErrorKind::ModuleNotFound(err) => {
799        Some(Cow::Borrowed(&err.specifier))
800      }
801      FinalizeResolutionErrorKind::TypesNotFound(err) => {
802        Some(Cow::Borrowed(&err.0.code_specifier))
803      }
804      FinalizeResolutionErrorKind::UnsupportedDirImport(err) => {
805        Some(Cow::Borrowed(&err.dir_url))
806      }
807      FinalizeResolutionErrorKind::PackageSubpathResolve(err) => {
808        err.maybe_specifier()
809      }
810      FinalizeResolutionErrorKind::InvalidModuleSpecifierError(_)
811      | FinalizeResolutionErrorKind::UrlToFilePath(_) => None,
812    }
813  }
814
815  pub fn as_types_not_found(&self) -> Option<&TypesNotFoundError> {
816    match self.as_kind() {
817      FinalizeResolutionErrorKind::TypesNotFound(err) => Some(err),
818      FinalizeResolutionErrorKind::PackageSubpathResolve(err) => {
819        err.as_types_not_found()
820      }
821      FinalizeResolutionErrorKind::ModuleNotFound(_)
822      | FinalizeResolutionErrorKind::UnsupportedDirImport(_)
823      | FinalizeResolutionErrorKind::InvalidModuleSpecifierError(_)
824      | FinalizeResolutionErrorKind::UrlToFilePath(_) => None,
825    }
826  }
827}
828
829#[derive(Debug, Error, JsError)]
830pub enum FinalizeResolutionErrorKind {
831  #[class(inherit)]
832  #[error(transparent)]
833  InvalidModuleSpecifierError(#[from] InvalidModuleSpecifierError),
834  #[class(inherit)]
835  #[error(transparent)]
836  ModuleNotFound(#[from] ModuleNotFoundError),
837  #[class(inherit)]
838  #[error(transparent)]
839  TypesNotFound(#[from] TypesNotFoundError),
840  #[class(inherit)]
841  #[error(transparent)]
842  PackageSubpathResolve(#[from] PackageSubpathResolveError),
843  #[class(inherit)]
844  #[error(transparent)]
845  UnsupportedDirImport(#[from] UnsupportedDirImportError),
846  #[class(inherit)]
847  #[error(transparent)]
848  #[property("code" = self.code())]
849  UrlToFilePath(#[from] deno_path_util::UrlToFilePathError),
850}
851
852impl NodeJsErrorCoded for FinalizeResolutionErrorKind {
853  fn code(&self) -> NodeJsErrorCode {
854    match self {
855      FinalizeResolutionErrorKind::InvalidModuleSpecifierError(e) => e.code(),
856      FinalizeResolutionErrorKind::ModuleNotFound(e) => e.code(),
857      FinalizeResolutionErrorKind::TypesNotFound(e) => e.code(),
858      FinalizeResolutionErrorKind::PackageSubpathResolve(e) => e.code(),
859      FinalizeResolutionErrorKind::UnsupportedDirImport(e) => e.code(),
860      FinalizeResolutionErrorKind::UrlToFilePath(_) => {
861        NodeJsErrorCode::ERR_INVALID_FILE_URL_PATH
862      }
863    }
864  }
865}
866
867#[derive(Debug, Error, JsError)]
868#[class(generic)]
869#[error(
870  "[{}] Cannot find module '{}'{}{}",
871  self.code(),
872  specifier,
873  maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default(),
874  suggested_ext.as_ref().map(|m| format!("\nDid you mean to import with the \".{}\" extension?", m)).unwrap_or_default()
875)]
876#[property("code" = self.code())]
877pub struct ModuleNotFoundError {
878  pub specifier: UrlOrPath,
879  pub maybe_referrer: Option<UrlOrPath>,
880  pub suggested_ext: Option<&'static str>,
881}
882
883impl NodeJsErrorCoded for ModuleNotFoundError {
884  fn code(&self) -> NodeJsErrorCode {
885    NodeJsErrorCode::ERR_MODULE_NOT_FOUND
886  }
887}
888
889#[derive(Debug, Error, JsError)]
890#[class(generic)]
891#[error(
892  "[{}] Directory import '{}' is not supported resolving ES modules{}{}",
893  self.code(),
894  dir_url,
895  maybe_referrer.as_ref().map(|referrer| format!(" imported from '{}'", referrer)).unwrap_or_default(),
896  suggestion.as_ref().map(|suggestion| format!("\nDid you mean to import '{suggestion}'?")).unwrap_or_default(),
897)]
898#[property("code" = self.code())]
899pub struct UnsupportedDirImportError {
900  pub dir_url: UrlOrPath,
901  pub maybe_referrer: Option<UrlOrPath>,
902  pub suggestion: Option<String>,
903}
904
905impl NodeJsErrorCoded for UnsupportedDirImportError {
906  fn code(&self) -> NodeJsErrorCode {
907    NodeJsErrorCode::ERR_UNSUPPORTED_DIR_IMPORT
908  }
909}
910
911#[derive(Debug, JsError)]
912#[class(generic)]
913#[property("code" = self.code())]
914pub struct InvalidPackageTargetError {
915  pub pkg_json_path: PathBuf,
916  pub sub_path: String,
917  pub target: String,
918  pub is_import: bool,
919  pub maybe_referrer: Option<UrlOrPath>,
920}
921
922impl std::error::Error for InvalidPackageTargetError {}
923
924impl std::fmt::Display for InvalidPackageTargetError {
925  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
926    let rel_error = !self.is_import
927      && !self.target.is_empty()
928      && !self.target.starts_with("./");
929    f.write_char('[')?;
930    f.write_str(self.code().as_str())?;
931    f.write_char(']')?;
932
933    if self.sub_path == "." {
934      assert!(!self.is_import);
935      write!(
936        f,
937        " Invalid \"exports\" main target {} defined in the package config {}",
938        self.target,
939        self.pkg_json_path.display()
940      )?;
941    } else {
942      let ie = if self.is_import { "imports" } else { "exports" };
943      write!(
944        f,
945        " Invalid \"{}\" target {} defined for '{}' in the package config {}",
946        ie,
947        self.target,
948        self.sub_path,
949        self.pkg_json_path.display()
950      )?;
951    };
952
953    if let Some(referrer) = &self.maybe_referrer {
954      write!(f, " imported from '{}'", referrer)?;
955    }
956    if rel_error {
957      write!(f, "; target must start with \"./\"")?;
958    }
959    Ok(())
960  }
961}
962
963impl NodeJsErrorCoded for InvalidPackageTargetError {
964  fn code(&self) -> NodeJsErrorCode {
965    NodeJsErrorCode::ERR_INVALID_PACKAGE_TARGET
966  }
967}
968
969#[derive(Debug, JsError)]
970#[class(generic)]
971#[property("code" = self.code())]
972pub struct PackagePathNotExportedError {
973  pub pkg_json_path: PathBuf,
974  pub subpath: String,
975  pub maybe_referrer: Option<UrlOrPath>,
976  pub resolution_kind: NodeResolutionKind,
977}
978
979impl NodeJsErrorCoded for PackagePathNotExportedError {
980  fn code(&self) -> NodeJsErrorCode {
981    NodeJsErrorCode::ERR_PACKAGE_PATH_NOT_EXPORTED
982  }
983}
984
985impl std::error::Error for PackagePathNotExportedError {}
986
987impl std::fmt::Display for PackagePathNotExportedError {
988  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
989    f.write_char('[')?;
990    f.write_str(self.code().as_str())?;
991    f.write_char(']')?;
992
993    let types_msg = match self.resolution_kind {
994      NodeResolutionKind::Execution => String::new(),
995      NodeResolutionKind::Types => " for types".to_string(),
996    };
997    if self.subpath == "." {
998      write!(
999        f,
1000        " No \"exports\" main defined{} in '{}'",
1001        types_msg,
1002        self.pkg_json_path.display()
1003      )?;
1004    } else {
1005      write!(
1006        f,
1007        " Package subpath '{}' is not defined{} by \"exports\" in '{}'",
1008        self.subpath,
1009        types_msg,
1010        self.pkg_json_path.display()
1011      )?;
1012    };
1013
1014    if let Some(referrer) = &self.maybe_referrer {
1015      write!(f, " imported from '{}'", referrer)?;
1016    }
1017    Ok(())
1018  }
1019}
1020
1021#[derive(Debug, Clone, Error, JsError)]
1022#[class(type)]
1023#[error(
1024  "[{}] Only file and data URLs are supported by the default ESM loader.{} Received protocol '{}'",
1025  self.code(),
1026  if cfg!(windows) && url_scheme.len() == 2 { " On Windows, absolute path must be valid file:// URLS."} else { "" },
1027  url_scheme
1028)]
1029#[property("code" = self.code())]
1030pub struct UnsupportedEsmUrlSchemeError {
1031  pub url_scheme: String,
1032}
1033
1034impl NodeJsErrorCoded for UnsupportedEsmUrlSchemeError {
1035  fn code(&self) -> NodeJsErrorCode {
1036    NodeJsErrorCode::ERR_UNSUPPORTED_ESM_URL_SCHEME
1037  }
1038}
1039
1040#[derive(Debug, Error, JsError)]
1041#[class(generic)]
1042#[error("Failed resolving binary export. '{}' did not exist", pkg_json_path.display())]
1043pub struct MissingPkgJsonError {
1044  pub pkg_json_path: PathBuf,
1045}
1046
1047#[derive(Debug, Error, JsError)]
1048pub enum ResolvePkgJsonBinExportError {
1049  #[class(inherit)]
1050  #[error(transparent)]
1051  ResolvePkgNpmBinaryCommands(#[from] ResolvePkgNpmBinaryCommandsError),
1052  #[class(generic)]
1053  #[error("Failed resolving binary export. {message}")]
1054  InvalidBinProperty { message: String },
1055}
1056
1057#[derive(Debug, Error, JsError)]
1058pub enum ResolvePkgNpmBinaryCommandsError {
1059  #[class(inherit)]
1060  #[error(transparent)]
1061  PkgJsonLoad(#[from] PackageJsonLoadError),
1062  #[class(generic)]
1063  #[error(transparent)]
1064  MissingPkgJson(#[from] MissingPkgJsonError),
1065  #[class(inherit)]
1066  #[error(transparent)]
1067  MissingPkgJsonName(#[from] MissingPkgJsonNameError),
1068}
1069
1070#[derive(Error, Debug, Clone, deno_error::JsError)]
1071#[class("NotFound")]
1072#[error("No such built-in module: node:{module_name}")]
1073#[property("code" = self.code())]
1074pub struct UnknownBuiltInNodeModuleError {
1075  /// Name of the invalid module.
1076  pub module_name: String,
1077}
1078
1079impl UnknownBuiltInNodeModuleError {
1080  pub fn maybe_specifier(&self) -> Option<Url> {
1081    Url::parse(&format!("node:{}", self.module_name)).ok()
1082  }
1083}
1084
1085impl NodeJsErrorCoded for UnknownBuiltInNodeModuleError {
1086  fn code(&self) -> NodeJsErrorCode {
1087    NodeJsErrorCode::ERR_UNKNOWN_BUILTIN_MODULE
1088  }
1089}
1090
1091#[cfg(test)]
1092mod test {
1093  use super::*;
1094
1095  #[test]
1096  fn types_resolution_package_path_not_exported() {
1097    let separator_char = if cfg!(windows) { '\\' } else { '/' };
1098    assert_eq!(
1099      PackagePathNotExportedError {
1100        pkg_json_path: PathBuf::from("test_path").join("package.json"),
1101        subpath: "./jsx-runtime".to_string(),
1102        maybe_referrer: None,
1103        resolution_kind: NodeResolutionKind::Types
1104      }
1105      .to_string(),
1106      format!(
1107        "[ERR_PACKAGE_PATH_NOT_EXPORTED] Package subpath './jsx-runtime' is not defined for types by \"exports\" in 'test_path{separator_char}package.json'"
1108      )
1109    );
1110    assert_eq!(
1111      PackagePathNotExportedError {
1112        pkg_json_path: PathBuf::from("test_path").join("package.json"),
1113        subpath: ".".to_string(),
1114        maybe_referrer: None,
1115        resolution_kind: NodeResolutionKind::Types
1116      }
1117      .to_string(),
1118      format!(
1119        "[ERR_PACKAGE_PATH_NOT_EXPORTED] No \"exports\" main defined for types in 'test_path{separator_char}package.json'"
1120      )
1121    );
1122  }
1123}