Repository: denoland/deno
Pull request: feat(cli): filter out common internal frames that add noise, dim and grey internal frames in stack traces

Before:
<img width="777" height="214" alt="Screenshot 2025-11-10 at 6 43 25 PM" src="https://github.com/user-attachments/assets/64faf089-738f-4b01-a075-e0e898f6b4d8" />
After:
<img width="777" height="134" alt="Screenshot 2025-11-10 at 6 41 41 PM" src="https://github.com/user-attachments/assets/4cf78714-5248-471f-8e73-7286f8e7b276" />


Changed files:
filename: Cargo.lock
patch: @@ -1639,7 +1639,7 @@ dependencies = [
  "deno_subprocess_windows",
  "deno_task_shell",
  "deno_telemetry",
- "deno_terminal 0.2.2",
+ "deno_terminal 0.2.3",
  "deno_tower_lsp",
  "deno_typescript_go_client_rust",
  "dhat",
@@ -1752,7 +1752,7 @@ dependencies = [
  "capacity_builder",
  "deno_error",
  "deno_media_type",
- "deno_terminal 0.2.2",
+ "deno_terminal 0.2.3",
  "dprint-swc-ext",
  "percent-encoding",
  "serde",
@@ -1906,9 +1906,9 @@ dependencies = [
 
 [[package]]
 name = "deno_core"
-version = "0.367.0"
+version = "0.368.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "35bc5bd853f22f22954aff45968f059e5f727755f1818dafba6c19cf1c6a43c2"
+checksum = "5ed73cb6f959f3692a8eb2eedd8e1a2a5e1d11dec141b4836fc21788402095f5"
 dependencies = [
  "anyhow",
  "az",
@@ -2020,7 +2020,7 @@ dependencies = [
  "deno_ast",
  "deno_graph",
  "deno_path_util",
- "deno_terminal 0.2.2",
+ "deno_terminal 0.2.3",
  "handlebars",
  "html-escape",
  "import_map",
@@ -2317,7 +2317,7 @@ dependencies = [
  "deno_resolver",
  "deno_runtime",
  "deno_semver",
- "deno_terminal 0.2.2",
+ "deno_terminal 0.2.3",
  "env_logger",
  "faster-hex",
  "indexmap 2.9.0",
@@ -2607,7 +2607,7 @@ dependencies = [
  "deno_path_util",
  "deno_resolver",
  "deno_semver",
- "deno_terminal 0.2.2",
+ "deno_terminal 0.2.3",
  "deno_unsync",
  "dyn-clone",
  "futures",
@@ -2629,9 +2629,9 @@ dependencies = [
 
 [[package]]
 name = "deno_ops"
-version = "0.243.0"
+version = "0.244.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "70093389f10651aada28d3b535e115aca21888d357e0346ba67ee63600a48218"
+checksum = "b4b6175c620af5e2ca21113dfb619d463796396082eec5bef030dc8ab1923055"
 dependencies = [
  "indexmap 2.9.0",
  "proc-macro-rules",
@@ -2711,7 +2711,7 @@ dependencies = [
  "chrono",
  "deno_error",
  "deno_path_util",
- "deno_terminal 0.2.2",
+ "deno_terminal 0.2.3",
  "deno_unsync",
  "fqdn",
  "ipnetwork",
@@ -2785,7 +2785,7 @@ dependencies = [
  "deno_path_util",
  "deno_permissions",
  "deno_semver",
- "deno_terminal 0.2.2",
+ "deno_terminal 0.2.3",
  "deno_unsync",
  "dissimilar",
  "futures",
@@ -2838,7 +2838,7 @@ dependencies = [
  "deno_resolver",
  "deno_signals",
  "deno_telemetry",
- "deno_terminal 0.2.2",
+ "deno_terminal 0.2.3",
  "deno_tls",
  "deno_web",
  "deno_webgpu",
@@ -2983,9 +2983,9 @@ dependencies = [
 
 [[package]]
 name = "deno_terminal"
-version = "0.2.2"
+version = "0.2.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "23f71c27009e0141dedd315f1dfa3ebb0a6ca4acce7c080fac576ea415a465f6"
+checksum = "f3ba8041ae7319b3ca6a64c399df4112badcbbe0868b4517637647614bede4be"
 dependencies = [
  "once_cell",
  "termcolor",
@@ -3253,7 +3253,7 @@ dependencies = [
  "deno_semver",
  "deno_snapshots",
  "deno_subprocess_windows",
- "deno_terminal 0.2.2",
+ "deno_terminal 0.2.3",
  "import_map",
  "indexmap 2.9.0",
  "libsui",
@@ -8254,9 +8254,9 @@ dependencies = [
 
 [[package]]
 name = "serde_v8"
-version = "0.276.0"
+version = "0.277.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "7d64a436af65a4fb070cd22d69d80bd97f5a9c67d31c2d0809a9fe0e84c59096"
+checksum = "def24655f388a9a7f07a350b822f82d4523e9f1c3a6d2e786a9da1520000a002"
 dependencies = [
  "deno_error",
  "num-bigint",

filename: Cargo.toml
patch: @@ -61,7 +61,7 @@ repository = "https://github.com/denoland/deno"
 
 [workspace.dependencies]
 deno_ast = { version = "=0.50.3", features = ["transpiling"] }
-deno_core = { version = "0.367.0" }
+deno_core = { version = "0.368.0" }
 
 deno_cache_dir = "=0.25.0"
 deno_doc = "=0.186.0"
@@ -75,7 +75,7 @@ deno_npm = "=0.42.0"
 deno_path_util = "=0.6.4"
 deno_semver = "=0.9.0"
 deno_task_shell = "=0.26.0"
-deno_terminal = "=0.2.2"
+deno_terminal = "=0.2.3"
 deno_unsync = { version = "0.4.4", default-features = false }
 deno_whoami = "0.1.0"
 eszip = "=0.104.0"

filename: ext/node/polyfills/internal/errors.ts
patch: @@ -151,15 +151,6 @@ function addNumericalSeparator(val: string) {
   return `${StringPrototypeSlice(val, 0, i)}${res}`;
 }
 
-const captureLargerStackTrace = hideStackFrames(
-  function captureLargerStackTrace(err) {
-    // @ts-ignore this function is not available in lib.dom.d.ts
-    ErrorCaptureStackTrace(err);
-
-    return err;
-  },
-);
-
 export interface ErrnoException extends Error {
   errno?: number;
   code?: string;
@@ -207,7 +198,7 @@ export const uvExceptionWithHostPort = hideStackFrames(
       ex.port = port;
     }
 
-    return captureLargerStackTrace(ex);
+    return ex;
   },
 );
 
@@ -235,7 +226,7 @@ export const errnoException = hideStackFrames(function errnoException(
   ex.code = code;
   ex.syscall = syscall;
 
-  return captureLargerStackTrace(ex);
+  return ex;
 });
 
 function uvErrmapGet(name: number) {
@@ -291,7 +282,7 @@ export const uvException = hideStackFrames(function uvException(ctx) {
     err.dest = dest;
   }
 
-  return captureLargerStackTrace(err);
+  return err;
 });
 
 /**
@@ -336,7 +327,7 @@ export const exceptionWithHostPort = hideStackFrames(
       ex.port = port;
     }
 
-    return captureLargerStackTrace(ex);
+    return ex;
   },
 );
 
@@ -376,7 +367,7 @@ export const dnsException = hideStackFrames(function (code, syscall, hostname) {
     ex.hostname = hostname;
   }
 
-  return captureLargerStackTrace(ex);
+  return ex;
 });
 
 /**
@@ -479,7 +470,7 @@ class NodeSystemError extends Error {
       message += ` => ${context.dest}`;
     }
 
-    captureLargerStackTrace(this);
+    ErrorCaptureStackTrace(this);
 
     ObjectDefineProperties(this, {
       [kIsNodeError]: {

filename: ext/webgpu/byow.rs
patch: @@ -257,13 +257,17 @@ impl<'a> FromV8<'a> for UnsafeWindowSurfaceOptions {
     let val = obj
       .get(scope, key.into())
       .ok_or_else(|| JsErrorBox::type_error("missing field 'width'"))?;
-    let width = deno_core::convert::Number::<u32>::from_v8(scope, val)?.0;
+    let width = deno_core::convert::Number::<u32>::from_v8(scope, val)
+      .map_err(JsErrorBox::from_err)?
+      .0;
 
     let key = v8::String::new(scope, "height").unwrap();
     let val = obj
       .get(scope, key.into())
       .ok_or_else(|| JsErrorBox::type_error("missing field 'height'"))?;
-    let height = deno_core::convert::Number::<u32>::from_v8(scope, val)?.0;
+    let height = deno_core::convert::Number::<u32>::from_v8(scope, val)
+      .map_err(JsErrorBox::from_err)?
+      .0;
 
     Ok(Self {
       system,

filename: runtime/fmt_errors.rs
patch: @@ -1,6 +1,8 @@
 // Copyright 2018-2025 the Deno authors. MIT license.
 //! This mod provides DenoError to unify errors across Deno.
+use std::borrow::Cow;
 use std::fmt::Write as _;
+use std::sync::LazyLock;
 
 use color_print::cformat;
 use color_print::cstr;
@@ -82,17 +84,21 @@ struct AnsiColors;
 impl deno_core::error::ErrorFormat for AnsiColors {
   fn fmt_element(
     element: deno_core::error::ErrorElement,
-    _in_extension_code: bool,
+    in_extension_code: bool,
     s: &str,
   ) -> std::borrow::Cow<'_, str> {
+    if in_extension_code {
+      return colors::dimmed_gray(s).to_string().into();
+    }
     use deno_core::error::ErrorElement::*;
     match element {
       Anonymous | NativeFrame | FileName | EvalOrigin => {
         colors::cyan(s).to_string().into()
       }
       LineNumber | ColumnNumber => colors::yellow(s).to_string().into(),
       FunctionName | PromiseAll => colors::italic_bold(s).to_string().into(),
-      WorkingDirPath => colors::gray(s).to_string().into(),
+      WorkingDirPath => colors::dimmed_gray(s).to_string().into(),
+      PlainText => s.into(),
     }
   }
 }
@@ -174,6 +180,7 @@ fn format_aggregated_error(
   aggregated_errors: &Vec<JsError>,
   circular_reference_index: usize,
   initial_cwd: Option<&Url>,
+  filter_frames: bool,
 ) -> String {
   let mut s = String::new();
   let mut nested_circular_reference_index = circular_reference_index;
@@ -190,6 +197,7 @@ fn format_aggregated_error(
         index: nested_circular_reference_index,
       }),
       false,
+      filter_frames,
       vec![],
       initial_cwd,
     );
@@ -202,10 +210,21 @@ fn format_aggregated_error(
   s
 }
 
+fn stack_frame_is_ext(frame: &deno_core::error::JsStackFrame) -> bool {
+  frame
+    .file_name
+    .as_ref()
+    .map(|file_name| {
+      file_name.starts_with("ext:") || file_name.starts_with("node:")
+    })
+    .unwrap_or(false)
+}
+
 fn format_js_error_inner(
   js_error: &JsError,
   circular: Option<IndexedErrorReference>,
   include_source_code: bool,
+  filter_frames: bool,
   suggestions: Vec<FixSuggestion>,
   initial_cwd: Option<&Url>,
 ) -> String {
@@ -228,6 +247,7 @@ fn format_js_error_inner(
         .map(|circular| circular.index)
         .unwrap_or(0),
       initial_cwd,
+      filter_frames,
     );
     s.push_str(&aggregated_message);
   }
@@ -245,10 +265,24 @@ fn format_js_error_inner(
     true,
     0,
   ));
+
+  let at_dimmed = Cow::Owned(colors::dimmed_gray("at ").to_string());
+  let at_normal = Cow::Borrowed("at ");
   for frame in &js_error.frames {
+    let is_ext = stack_frame_is_ext(frame);
+    if filter_frames
+      && is_ext
+      && let Some(fn_name) = &frame.function_name
+      && (fn_name.starts_with("__node_internal_")
+        || fn_name == "eventLoopTick"
+        || fn_name == "denoErrorToNodeError")
+    {
+      continue;
+    }
     write!(
       s,
-      "\n    at {}",
+      "\n    {}{}",
+      if is_ext { &at_dimmed } else { &at_normal },
       format_frame::<AnsiColors>(frame, initial_cwd)
     )
     .unwrap();
@@ -263,7 +297,7 @@ fn format_js_error_inner(
       colors::cyan(format!("[Circular *{}]", circular.unwrap().index))
         .to_string()
     } else {
-      format_js_error_inner(cause, circular, false, vec![], initial_cwd)
+      format_js_error_inner(cause, circular, false, false, vec![], initial_cwd)
     };
 
     write!(
@@ -476,6 +510,9 @@ fn get_suggestions_for_terminal_errors(e: &JsError) -> Vec<FixSuggestion<'_>> {
   vec![]
 }
 
+static SHOULD_FILTER_FRAMES: LazyLock<bool> =
+  LazyLock::new(|| std::env::var("DENO_NO_FILTER_FRAMES").is_err());
+
 /// Format a [`JsError`] for terminal output.
 pub fn format_js_error(
   js_error: &JsError,
@@ -487,7 +524,14 @@ pub fn format_js_error(
       index: 1,
     });
   let suggestions = get_suggestions_for_terminal_errors(js_error);
-  format_js_error_inner(js_error, circular, true, suggestions, initial_cwd)
+  format_js_error_inner(
+    js_error,
+    circular,
+    true,
+    *SHOULD_FILTER_FRAMES,
+    suggestions,
+    initial_cwd,
+  )
 }
 
 #[cfg(test)]