diff --git a/crates/biome_diagnostics_categories/src/categories.rs b/crates/biome_diagnostics_categories/src/categories.rs
index d9a11911ad35..547d0b6f2d0b 100644
--- a/crates/biome_diagnostics_categories/src/categories.rs
+++ b/crates/biome_diagnostics_categories/src/categories.rs
@@ -92,6 +92,7 @@ define_categories! {
     "lint/nursery/noApproximativeNumericConstant": "https://biomejs.dev/lint/rules/no-approximative-numeric-constant",
     "lint/nursery/noConfusingVoidType": "https://biomejs.dev/linter/rules/no-confusing-void-type",
     "lint/nursery/noDuplicateJsonKeys": "https://biomejs.dev/linter/rules/no-duplicate-json-keys",
+    "lint/nursery/noEmptyBlockStatements": "https://biomejs.dev/lint/rules/no-empty-block-statements",
     "lint/nursery/noEmptyCharacterClassInRegex": "https://biomejs.dev/lint/rules/no-empty-character-class-in-regex",
     "lint/nursery/noExcessiveComplexity": "https://biomejs.dev/linter/rules/no-excessive-complexity",
     "lint/nursery/noFallthroughSwitchClause": "https://biomejs.dev/linter/rules/no-fallthrough-switch-clause",
diff --git a/crates/biome_js_analyze/src/analyzers/nursery.rs b/crates/biome_js_analyze/src/analyzers/nursery.rs
index 14ab06897314..6a248b7fb40d 100644
--- a/crates/biome_js_analyze/src/analyzers/nursery.rs
+++ b/crates/biome_js_analyze/src/analyzers/nursery.rs
@@ -4,6 +4,7 @@ use biome_analyze::declare_group;
 
 pub(crate) mod no_approximative_numeric_constant;
 pub(crate) mod no_confusing_void_type;
+pub(crate) mod no_empty_block_statements;
 pub(crate) mod no_empty_character_class_in_regex;
 pub(crate) mod no_excessive_complexity;
 pub(crate) mod no_fallthrough_switch_clause;
@@ -25,6 +26,7 @@ declare_group! {
         rules : [
             self :: no_approximative_numeric_constant :: NoApproximativeNumericConstant ,
             self :: no_confusing_void_type :: NoConfusingVoidType ,
+            self :: no_empty_block_statements :: NoEmptyBlockStatements ,
             self :: no_empty_character_class_in_regex :: NoEmptyCharacterClassInRegex ,
             self :: no_excessive_complexity :: NoExcessiveComplexity ,
             self :: no_fallthrough_switch_clause :: NoFallthroughSwitchClause ,
diff --git a/crates/biome_js_analyze/src/analyzers/nursery/no_empty_block_statements.rs b/crates/biome_js_analyze/src/analyzers/nursery/no_empty_block_statements.rs
new file mode 100644
index 000000000000..6c4f10f471df
--- /dev/null
+++ b/crates/biome_js_analyze/src/analyzers/nursery/no_empty_block_statements.rs
@@ -0,0 +1,107 @@
+use biome_analyze::{context::RuleContext, declare_rule, Ast, Rule, RuleDiagnostic};
+use biome_console::markup;
+use biome_js_syntax::{
+    JsBlockStatement, JsFunctionBody, JsStaticInitializationBlockClassMember, JsSwitchStatement,
+};
+use biome_rowan::{declare_node_union, AstNode, AstNodeList};
+
+declare_rule! {
+    /// Disallow empty block statements and static blocks.
+    ///
+    /// Empty static blocks and block statements, while not technically errors, usually occur due to refactoring that wasn’t completed. They can cause confusion when reading code.
+    ///
+    /// This rule disallows empty block statements and static blocks.
+    /// This rule ignores block statements or static blocks which contain a comment (for example, in an empty catch or finally block of a try statement to indicate that execution should continue regardless of errors).
+    ///
+    /// Source: https://eslint.org/docs/latest/rules/no-empty-static-block/
+    /// Source: https://eslint.org/docs/latest/rules/no-empty/
+    ///
+    /// ## Examples
+    ///
+    /// ### Invalid
+    ///
+    /// ```js,expect_diagnostic
+    /// function emptyFunctionBody () {}
+    /// ```
+    ///
+    /// ```js,expect_diagnostic
+    /// try {
+    ///     doSomething();
+    /// } catch(ex) {
+    ///
+    /// }
+    /// ```
+    ///
+    /// ```js,expect_diagnostic
+    /// class Foo {
+    ///   static {}
+    /// }
+    /// ```
+    ///
+    /// ## Valid
+    ///
+    /// ```js
+    /// function foo () {
+    ///     doSomething();
+    /// }
+    /// ```
+    ///
+    /// ```js
+    /// try {
+    ///   doSomething();
+    /// } catch (ex) {
+    ///   // continue regardless of error
+    /// }
+    /// ```
+    ///
+    pub(crate) NoEmptyBlockStatements {
+        version: "next",
+        name: "noEmptyBlockStatements",
+        recommended: false,
+    }
+}
+
+declare_node_union! {
+    pub(crate) Query = JsBlockStatement | JsFunctionBody | JsStaticInitializationBlockClassMember | JsSwitchStatement
+}
+
+impl Rule for NoEmptyBlockStatements {
+    type Query = Ast<Query>;
+    type State = ();
+    type Signals = Option<Self::State>;
+    type Options = ();
+
+    fn run(ctx: &RuleContext<Self>) -> Self::Signals {
+        let query = ctx.query();
+        let is_empty = is_empty(query);
+        let has_comments = query.syntax().has_comments_descendants();
+
+        (is_empty && !has_comments).then_some(())
+    }
+
+    fn diagnostic(ctx: &RuleContext<Self>, _: &Self::State) -> Option<RuleDiagnostic> {
+        let query = ctx.query();
+        Some(
+            RuleDiagnostic::new(
+                rule_category!(),
+                query.range(),
+                markup! {
+                    "Unexpected empty block."
+                },
+            )
+            .note(markup! {
+                "Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional."
+            }),
+        )
+    }
+}
+
+fn is_empty(query: &Query) -> bool {
+    use Query::*;
+    match query {
+        JsFunctionBody(body) => body.directives().len() == 0 && body.statements().len() == 0,
+        JsBlockStatement(block) => block.statements().len() == 0,
+        JsStaticInitializationBlockClassMember(block) => block.statements().len() == 0,
+        JsSwitchStatement(statement) => statement.cases().len() == 0,
+    }
+}
diff --git a/crates/biome_js_analyze/src/options.rs b/crates/biome_js_analyze/src/options.rs
index 67040c65d53f..df477f1ab4d7 100644
--- a/crates/biome_js_analyze/src/options.rs
+++ b/crates/biome_js_analyze/src/options.rs
@@ -134,7 +134,6 @@ impl PossibleOptions {
                     options.visit_map(key.syntax(), value.syntax(), diagnostics)?;
                     *self = PossibleOptions::RestrictedGlobals(options);
                 }
-
                 _ => (),
             }
         }
diff --git a/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.js b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.js
new file mode 100644
index 000000000000..548120a96ab0
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.js
@@ -0,0 +1,69 @@
+function foo() {}
+
+const bar = () => {};
+
+function fooWithNestedEmptyFnBlock() {
+  let a = 1;
+
+  function shouldFail(){}
+
+  return a
+}
+
+
+const barWithNestedEmptyFnBlock = () => {
+  let a = 1;
+
+  const shouldFail = () => {}
+
+  return a
+}
+
+let someVar;
+if (someVar) {
+}
+
+while (someVar) {
+}
+
+switch(someVar) {
+}
+
+try {
+    doSomething();
+} catch(ex) {
+
+} finally {
+
+}
+
+class Foo {
+  static {}
+}
+
+for(let i; i>0; i++){}
+
+const ob = {}
+for (key in ob) {}
+
+const ar = []
+for (val of ar) {}
+
+function fooWithInternalEmptyBlocks(){
+  let someVar;
+  if (someVar) {}
+
+  while (someVar) {
+  }
+
+  switch(someVar) {
+  }
+
+  try {
+      doSomething();
+  } catch(ex) {
+
+  } finally {
+
+  }
+}
\ No newline at end of file
diff --git a/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.js.snap b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.js.snap
new file mode 100644
index 000000000000..f7cbb2b499ca
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.js.snap
@@ -0,0 +1,400 @@
+---
+source: crates/biome_js_analyze/tests/spec_tests.rs
+expression: invalid.js
+---
+# Input
+```js
+function foo() {}
+
+const bar = () => {};
+
+function fooWithNestedEmptyFnBlock() {
+  let a = 1;
+
+  function shouldFail(){}
+
+  return a
+}
+
+
+const barWithNestedEmptyFnBlock = () => {
+  let a = 1;
+
+  const shouldFail = () => {}
+
+  return a
+}
+
+let someVar;
+if (someVar) {
+}
+
+while (someVar) {
+}
+
+switch(someVar) {
+}
+
+try {
+    doSomething();
+} catch(ex) {
+
+} finally {
+
+}
+
+class Foo {
+  static {}
+}
+
+for(let i; i>0; i++){}
+
+const ob = {}
+for (key in ob) {}
+
+const ar = []
+for (val of ar) {}
+
+function fooWithInternalEmptyBlocks(){
+  let someVar;
+  if (someVar) {}
+
+  while (someVar) {
+  }
+
+  switch(someVar) {
+  }
+
+  try {
+      doSomething();
+  } catch(ex) {
+
+  } finally {
+
+  }
+}
+```
+
+# Diagnostics
+```
+invalid.js:1:16 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+  > 1 │ function foo() {}
+      │                ^^
+    2 │ 
+    3 │ const bar = () => {};
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:3:19 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    1 │ function foo() {}
+    2 │ 
+  > 3 │ const bar = () => {};
+      │                   ^^
+    4 │ 
+    5 │ function fooWithNestedEmptyFnBlock() {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:8:24 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+     6 │   let a = 1;
+     7 │ 
+   > 8 │   function shouldFail(){}
+       │                        ^^
+     9 │ 
+    10 │   return a
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:17:28 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    15 │   let a = 1;
+    16 │ 
+  > 17 │   const shouldFail = () => {}
+       │                            ^^
+    18 │ 
+    19 │   return a
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:23:14 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    22 │ let someVar;
+  > 23 │ if (someVar) {
+       │              ^
+  > 24 │ }
+       │ ^
+    25 │ 
+    26 │ while (someVar) {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:26:17 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    24 │ }
+    25 │ 
+  > 26 │ while (someVar) {
+       │                 ^
+  > 27 │ }
+       │ ^
+    28 │ 
+    29 │ switch(someVar) {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:29:1 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    27 │ }
+    28 │ 
+  > 29 │ switch(someVar) {
+       │ ^^^^^^^^^^^^^^^^^
+  > 30 │ }
+       │ ^
+    31 │ 
+    32 │ try {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:34:13 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    32 │ try {
+    33 │     doSomething();
+  > 34 │ } catch(ex) {
+       │             ^
+  > 35 │ 
+  > 36 │ } finally {
+       │ ^
+    37 │ 
+    38 │ }
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:36:11 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    34 │ } catch(ex) {
+    35 │ 
+  > 36 │ } finally {
+       │           ^
+  > 37 │ 
+  > 38 │ }
+       │ ^
+    39 │ 
+    40 │ class Foo {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:41:3 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    40 │ class Foo {
+  > 41 │   static {}
+       │   ^^^^^^^^^
+    42 │ }
+    43 │ 
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:44:21 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    42 │ }
+    43 │ 
+  > 44 │ for(let i; i>0; i++){}
+       │                     ^^
+    45 │ 
+    46 │ const ob = {}
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:47:17 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    46 │ const ob = {}
+  > 47 │ for (key in ob) {}
+       │                 ^^
+    48 │ 
+    49 │ const ar = []
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:50:17 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    49 │ const ar = []
+  > 50 │ for (val of ar) {}
+       │                 ^^
+    51 │ 
+    52 │ function fooWithInternalEmptyBlocks(){
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:54:16 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    52 │ function fooWithInternalEmptyBlocks(){
+    53 │   let someVar;
+  > 54 │   if (someVar) {}
+       │                ^^
+    55 │ 
+    56 │   while (someVar) {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:56:19 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    54 │   if (someVar) {}
+    55 │ 
+  > 56 │   while (someVar) {
+       │                   ^
+  > 57 │   }
+       │   ^
+    58 │ 
+    59 │   switch(someVar) {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:59:3 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    57 │   }
+    58 │ 
+  > 59 │   switch(someVar) {
+       │   ^^^^^^^^^^^^^^^^^
+  > 60 │   }
+       │   ^
+    61 │ 
+    62 │   try {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:64:15 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    62 │   try {
+    63 │       doSomething();
+  > 64 │   } catch(ex) {
+       │               ^
+  > 65 │ 
+  > 66 │   } finally {
+       │   ^
+    67 │ 
+    68 │   }
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.js:66:13 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    64 │   } catch(ex) {
+    65 │ 
+  > 66 │   } finally {
+       │             ^
+  > 67 │ 
+  > 68 │   }
+       │   ^
+    69 │ }
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+
diff --git a/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.ts b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.ts
new file mode 100644
index 000000000000..00f3253ca85c
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.ts
@@ -0,0 +1,70 @@
+function fooEmptyTs() {}
+
+const barEmptyTs = () => {};
+
+function fooWithNestedEmptyFnBlockTs() {
+  let a = 1;
+
+  function shouldFail(){}
+
+  return a
+}
+
+
+const barWithNestedEmptyFnBlockTs = () => {
+  let a = 1;
+
+  const shouldFail = () => {}
+
+  return a
+}
+
+const someVarTs: string = '';
+if (someVarTs) {
+}
+
+while (someVarTs) {
+}
+
+switch(someVarTs) {
+}
+
+const doSomething = () => null;
+try {
+    doSomething();
+} catch(ex) {
+
+} finally {
+
+}
+
+class FooEmptyStaticTs {
+  static {}
+}
+
+for(let i; i>0; i++){}
+
+const obTs = {}
+for (const key in obTs) {}
+
+const arTs = []
+for (const val of arTs) {}
+
+function fooWithInternalEmptyBlocksTs(){
+  let someOtherVar: string = '';
+  if (someOtherVar) {}
+
+  while (someOtherVar) {
+  }
+
+  switch(someOtherVar) {
+  }
+
+  try {
+      doSomething();
+  } catch(ex) {
+
+  } finally {
+
+  }
+}
\ No newline at end of file
diff --git a/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.ts.snap b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.ts.snap
new file mode 100644
index 000000000000..5b4b353bf9c7
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/invalid.ts.snap
@@ -0,0 +1,401 @@
+---
+source: crates/biome_js_analyze/tests/spec_tests.rs
+expression: invalid.ts
+---
+# Input
+```js
+function fooEmptyTs() {}
+
+const barEmptyTs = () => {};
+
+function fooWithNestedEmptyFnBlockTs() {
+  let a = 1;
+
+  function shouldFail(){}
+
+  return a
+}
+
+
+const barWithNestedEmptyFnBlockTs = () => {
+  let a = 1;
+
+  const shouldFail = () => {}
+
+  return a
+}
+
+const someVarTs: string = '';
+if (someVarTs) {
+}
+
+while (someVarTs) {
+}
+
+switch(someVarTs) {
+}
+
+const doSomething = () => null;
+try {
+    doSomething();
+} catch(ex) {
+
+} finally {
+
+}
+
+class FooEmptyStaticTs {
+  static {}
+}
+
+for(let i; i>0; i++){}
+
+const obTs = {}
+for (const key in obTs) {}
+
+const arTs = []
+for (const val of arTs) {}
+
+function fooWithInternalEmptyBlocksTs(){
+  let someOtherVar: string = '';
+  if (someOtherVar) {}
+
+  while (someOtherVar) {
+  }
+
+  switch(someOtherVar) {
+  }
+
+  try {
+      doSomething();
+  } catch(ex) {
+
+  } finally {
+
+  }
+}
+```
+
+# Diagnostics
+```
+invalid.ts:1:23 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+  > 1 │ function fooEmptyTs() {}
+      │                       ^^
+    2 │ 
+    3 │ const barEmptyTs = () => {};
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:3:26 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    1 │ function fooEmptyTs() {}
+    2 │ 
+  > 3 │ const barEmptyTs = () => {};
+      │                          ^^
+    4 │ 
+    5 │ function fooWithNestedEmptyFnBlockTs() {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:8:24 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+     6 │   let a = 1;
+     7 │ 
+   > 8 │   function shouldFail(){}
+       │                        ^^
+     9 │ 
+    10 │   return a
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:17:28 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    15 │   let a = 1;
+    16 │ 
+  > 17 │   const shouldFail = () => {}
+       │                            ^^
+    18 │ 
+    19 │   return a
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:23:16 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    22 │ const someVarTs: string = '';
+  > 23 │ if (someVarTs) {
+       │                ^
+  > 24 │ }
+       │ ^
+    25 │ 
+    26 │ while (someVarTs) {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:26:19 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    24 │ }
+    25 │ 
+  > 26 │ while (someVarTs) {
+       │                   ^
+  > 27 │ }
+       │ ^
+    28 │ 
+    29 │ switch(someVarTs) {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:29:1 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    27 │ }
+    28 │ 
+  > 29 │ switch(someVarTs) {
+       │ ^^^^^^^^^^^^^^^^^^^
+  > 30 │ }
+       │ ^
+    31 │ 
+    32 │ const doSomething = () => null;
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:35:13 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    33 │ try {
+    34 │     doSomething();
+  > 35 │ } catch(ex) {
+       │             ^
+  > 36 │ 
+  > 37 │ } finally {
+       │ ^
+    38 │ 
+    39 │ }
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:37:11 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    35 │ } catch(ex) {
+    36 │ 
+  > 37 │ } finally {
+       │           ^
+  > 38 │ 
+  > 39 │ }
+       │ ^
+    40 │ 
+    41 │ class FooEmptyStaticTs {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:42:3 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    41 │ class FooEmptyStaticTs {
+  > 42 │   static {}
+       │   ^^^^^^^^^
+    43 │ }
+    44 │ 
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:45:21 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    43 │ }
+    44 │ 
+  > 45 │ for(let i; i>0; i++){}
+       │                     ^^
+    46 │ 
+    47 │ const obTs = {}
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:48:25 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    47 │ const obTs = {}
+  > 48 │ for (const key in obTs) {}
+       │                         ^^
+    49 │ 
+    50 │ const arTs = []
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:51:25 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    50 │ const arTs = []
+  > 51 │ for (const val of arTs) {}
+       │                         ^^
+    52 │ 
+    53 │ function fooWithInternalEmptyBlocksTs(){
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:55:21 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    53 │ function fooWithInternalEmptyBlocksTs(){
+    54 │   let someOtherVar: string = '';
+  > 55 │   if (someOtherVar) {}
+       │                     ^^
+    56 │ 
+    57 │   while (someOtherVar) {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:57:24 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    55 │   if (someOtherVar) {}
+    56 │ 
+  > 57 │   while (someOtherVar) {
+       │                        ^
+  > 58 │   }
+       │   ^
+    59 │ 
+    60 │   switch(someOtherVar) {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:60:3 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    58 │   }
+    59 │ 
+  > 60 │   switch(someOtherVar) {
+       │   ^^^^^^^^^^^^^^^^^^^^^^
+  > 61 │   }
+       │   ^
+    62 │ 
+    63 │   try {
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:65:15 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    63 │   try {
+    64 │       doSomething();
+  > 65 │   } catch(ex) {
+       │               ^
+  > 66 │ 
+  > 67 │   } finally {
+       │   ^
+    68 │ 
+    69 │   }
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+```
+invalid.ts:67:13 lint/nursery/noEmptyBlockStatements ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+  ! Unexpected empty block.
+  
+    65 │   } catch(ex) {
+    66 │ 
+  > 67 │   } finally {
+       │             ^
+  > 68 │ 
+  > 69 │   }
+       │   ^
+    70 │ }
+  
+  i Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.
+  
+
+```
+
+
diff --git a/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.cjs b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.cjs
new file mode 100644
index 000000000000..d826dcb0c71f
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.cjs
@@ -0,0 +1,67 @@
+/* should not generate diagnostics */
+function foo() {
+  let a;
+}
+
+const bar = () => {
+  let b;
+}
+
+
+function fooWithComment() {
+  // should work
+}
+
+const barWithComment = () => {
+  // should work
+}
+
+function fooWithMultilineComment() {
+  /**
+   * this should also work 
+   */
+}
+
+const barWithMultilineComment = () => {
+  /**
+   * this should also work 
+   */
+}
+
+
+if (foo) {
+  // empty
+}
+
+while (foo) {
+  /* empty */
+}
+
+try {
+  doSomething();
+} catch (ex) {
+  // continue regardless of error
+}
+
+try {
+  doSomething();
+} finally {
+  /* continue regardless of error */
+}
+
+class Foo {
+  static {
+      bar();
+  }
+}
+
+class Foo {
+  static {
+      // comment
+  }
+}
+
+// biome-ignore lint/nursery/noEmptyBlockStatements: this should be allowed
+function shouldNotFail() {
+
+}
\ No newline at end of file
diff --git a/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.cjs.snap b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.cjs.snap
new file mode 100644
index 000000000000..bf68c75b8207
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.cjs.snap
@@ -0,0 +1,76 @@
+---
+source: crates/biome_js_analyze/tests/spec_tests.rs
+expression: valid.cjs
+---
+# Input
+```js
+/* should not generate diagnostics */
+function foo() {
+  let a;
+}
+
+const bar = () => {
+  let b;
+}
+
+
+function fooWithComment() {
+  // should work
+}
+
+const barWithComment = () => {
+  // should work
+}
+
+function fooWithMultilineComment() {
+  /**
+   * this should also work 
+   */
+}
+
+const barWithMultilineComment = () => {
+  /**
+   * this should also work 
+   */
+}
+
+
+if (foo) {
+  // empty
+}
+
+while (foo) {
+  /* empty */
+}
+
+try {
+  doSomething();
+} catch (ex) {
+  // continue regardless of error
+}
+
+try {
+  doSomething();
+} finally {
+  /* continue regardless of error */
+}
+
+class Foo {
+  static {
+      bar();
+  }
+}
+
+class Foo {
+  static {
+      // comment
+  }
+}
+
+// biome-ignore lint/nursery/noEmptyBlockStatements: this should be allowed
+function shouldNotFail() {
+
+}
+```
+
+
diff --git a/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.js b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.js
new file mode 100644
index 000000000000..d826dcb0c71f
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.js
@@ -0,0 +1,67 @@
+/* should not generate diagnostics */
+function foo() {
+  let a;
+}
+
+const bar = () => {
+  let b;
+}
+
+
+function fooWithComment() {
+  // should work
+}
+
+const barWithComment = () => {
+  // should work
+}
+
+function fooWithMultilineComment() {
+  /**
+   * this should also work 
+   */
+}
+
+const barWithMultilineComment = () => {
+  /**
+   * this should also work 
+   */
+}
+
+
+if (foo) {
+  // empty
+}
+
+while (foo) {
+  /* empty */
+}
+
+try {
+  doSomething();
+} catch (ex) {
+  // continue regardless of error
+}
+
+try {
+  doSomething();
+} finally {
+  /* continue regardless of error */
+}
+
+class Foo {
+  static {
+      bar();
+  }
+}
+
+class Foo {
+  static {
+      // comment
+  }
+}
+
+// biome-ignore lint/nursery/noEmptyBlockStatements: this should be allowed
+function shouldNotFail() {
+
+}
\ No newline at end of file
diff --git a/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.js.snap b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.js.snap
new file mode 100644
index 000000000000..ad4ba867b365
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.js.snap
@@ -0,0 +1,76 @@
+---
+source: crates/biome_js_analyze/tests/spec_tests.rs
+expression: valid.js
+---
+# Input
+```js
+/* should not generate diagnostics */
+function foo() {
+  let a;
+}
+
+const bar = () => {
+  let b;
+}
+
+
+function fooWithComment() {
+  // should work
+}
+
+const barWithComment = () => {
+  // should work
+}
+
+function fooWithMultilineComment() {
+  /**
+   * this should also work 
+   */
+}
+
+const barWithMultilineComment = () => {
+  /**
+   * this should also work 
+   */
+}
+
+
+if (foo) {
+  // empty
+}
+
+while (foo) {
+  /* empty */
+}
+
+try {
+  doSomething();
+} catch (ex) {
+  // continue regardless of error
+}
+
+try {
+  doSomething();
+} finally {
+  /* continue regardless of error */
+}
+
+class Foo {
+  static {
+      bar();
+  }
+}
+
+class Foo {
+  static {
+      // comment
+  }
+}
+
+// biome-ignore lint/nursery/noEmptyBlockStatements: this should be allowed
+function shouldNotFail() {
+
+}
+```
+
+
diff --git a/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.ts b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.ts
new file mode 100644
index 000000000000..cefcd5d4d65d
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.ts
@@ -0,0 +1,68 @@
+/* should not generate diagnostics */
+function fooTs() {
+  let a;
+}
+
+const barTs = () => {
+  let b;
+}
+
+
+function fooWithCommentTS() {
+  // should work
+}
+
+const barWithCommentTs = () => {
+  // should work
+}
+
+function fooWithMultilineCommentTS() {
+  /**
+   * this should also work 
+   */
+}
+
+const barWithMultilineCommentTs = () => {
+  /**
+   * this should also work 
+   */
+}
+
+let fooVarTs;
+if (fooVarTs) {
+  // empty
+}
+
+while (fooVarTs) {
+  /* empty */
+}
+
+const doSomethingTs = () => null;
+try {
+  doSomethingTs();
+} catch (ex) {
+  // continue regardless of error
+}
+
+try {
+  doSomethingTs();
+} finally {
+  /* continue regardless of error */
+}
+
+class FooTs {
+  static {
+      bar();
+  }
+}
+
+class FoozTs {
+  static {
+      // comment
+  }
+}
+
+// biome-ignore lint/nursery/noEmptyBlockStatements: this should be allowed
+function shouldNotFailTs() {
+
+}
\ No newline at end of file
diff --git a/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.ts.snap b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.ts.snap
new file mode 100644
index 000000000000..8e70c1c1f43c
--- /dev/null
+++ b/crates/biome_js_analyze/tests/specs/nursery/noEmptyBlockStatements/valid.ts.snap
@@ -0,0 +1,77 @@
+---
+source: crates/biome_js_analyze/tests/spec_tests.rs
+expression: valid.ts
+---
+# Input
+```js
+/* should not generate diagnostics */
+function fooTs() {
+  let a;
+}
+
+const barTs = () => {
+  let b;
+}
+
+
+function fooWithCommentTS() {
+  // should work
+}
+
+const barWithCommentTs = () => {
+  // should work
+}
+
+function fooWithMultilineCommentTS() {
+  /**
+   * this should also work 
+   */
+}
+
+const barWithMultilineCommentTs = () => {
+  /**
+   * this should also work 
+   */
+}
+
+let fooVarTs;
+if (fooVarTs) {
+  // empty
+}
+
+while (fooVarTs) {
+  /* empty */
+}
+
+const doSomethingTs = () => null;
+try {
+  doSomethingTs();
+} catch (ex) {
+  // continue regardless of error
+}
+
+try {
+  doSomethingTs();
+} finally {
+  /* continue regardless of error */
+}
+
+class FooTs {
+  static {
+      bar();
+  }
+}
+
+class FoozTs {
+  static {
+      // comment
+  }
+}
+
+// biome-ignore lint/nursery/noEmptyBlockStatements: this should be allowed
+function shouldNotFailTs() {
+
+}
+```
+
+
diff --git a/crates/biome_service/src/configuration/linter/rules.rs b/crates/biome_service/src/configuration/linter/rules.rs
index ab8a9b900425..dca7c4c64ca5 100644
--- a/crates/biome_service/src/configuration/linter/rules.rs
+++ b/crates/biome_service/src/configuration/linter/rules.rs
@@ -2184,6 +2184,15 @@ pub struct Nursery {
     )]
     #[serde(skip_serializing_if = "Option::is_none")]
     pub no_duplicate_json_keys: Option<RuleConfiguration>,
+    #[doc = "Disallow empty block statements and static blocks."]
+    #[bpaf(
+        long("no-empty-block-statements"),
+        argument("on|off|warn"),
+        optional,
+        hide
+    )]
+    #[serde(skip_serializing_if = "Option::is_none")]
+    pub no_empty_block_statements: Option<RuleConfiguration>,
     #[doc = "Disallow empty character classes in regular expression literals."]
     #[bpaf(
         long("no-empty-character-class-in-regex"),
@@ -2344,11 +2353,12 @@ pub struct Nursery {
 }
 impl Nursery {
     const GROUP_NAME: &'static str = "nursery";
-    pub(crate) const GROUP_RULES: [&'static str; 27] = [
+    pub(crate) const GROUP_RULES: [&'static str; 28] = [
         "noAccumulatingSpread",
         "noApproximativeNumericConstant",
         "noConfusingVoidType",
         "noDuplicateJsonKeys",
+        "noEmptyBlockStatements",
         "noEmptyCharacterClassInRegex",
         "noExcessiveComplexity",
         "noFallthroughSwitchClause",
@@ -2389,19 +2399,19 @@ impl Nursery {
     ];
     const RECOMMENDED_RULES_AS_FILTERS: [RuleFilter<'static>; 12] = [
         RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[3]),
-        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[4]),
-        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[7]),
+        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[5]),
         RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[8]),
-        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[10]),
+        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[9]),
         RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[11]),
-        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14]),
-        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18]),
+        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[12]),
+        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[15]),
         RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19]),
-        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21]),
+        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20]),
         RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22]),
-        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25]),
+        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23]),
+        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26]),
     ];
-    const ALL_RULES_AS_FILTERS: [RuleFilter<'static>; 27] = [
+    const ALL_RULES_AS_FILTERS: [RuleFilter<'static>; 28] = [
         RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[0]),
         RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[1]),
         RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[2]),
@@ -2429,6 +2439,7 @@ impl Nursery {
         RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24]),
         RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25]),
         RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26]),
+        RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27]),
     ];
     #[doc = r" Retrieves the recommended rules"]
     pub(crate) fn is_recommended(&self) -> bool {
@@ -2465,121 +2476,126 @@ impl Nursery {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[3]));
             }
         }
-        if let Some(rule) = self.no_empty_character_class_in_regex.as_ref() {
+        if let Some(rule) = self.no_empty_block_statements.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[4]));
             }
         }
-        if let Some(rule) = self.no_excessive_complexity.as_ref() {
+        if let Some(rule) = self.no_empty_character_class_in_regex.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[5]));
             }
         }
-        if let Some(rule) = self.no_fallthrough_switch_clause.as_ref() {
+        if let Some(rule) = self.no_excessive_complexity.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[6]));
             }
         }
-        if let Some(rule) = self.no_global_is_finite.as_ref() {
+        if let Some(rule) = self.no_fallthrough_switch_clause.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[7]));
             }
         }
-        if let Some(rule) = self.no_global_is_nan.as_ref() {
+        if let Some(rule) = self.no_global_is_finite.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[8]));
             }
         }
-        if let Some(rule) = self.no_interactive_element_to_noninteractive_role.as_ref() {
+        if let Some(rule) = self.no_global_is_nan.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[9]));
             }
         }
-        if let Some(rule) = self.no_invalid_new_builtin.as_ref() {
+        if let Some(rule) = self.no_interactive_element_to_noninteractive_role.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[10]));
             }
         }
-        if let Some(rule) = self.no_misleading_instantiator.as_ref() {
+        if let Some(rule) = self.no_invalid_new_builtin.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[11]));
             }
         }
-        if let Some(rule) = self.no_misrefactored_shorthand_assign.as_ref() {
+        if let Some(rule) = self.no_misleading_instantiator.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[12]));
             }
         }
-        if let Some(rule) = self.no_unused_imports.as_ref() {
+        if let Some(rule) = self.no_misrefactored_shorthand_assign.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13]));
             }
         }
-        if let Some(rule) = self.no_useless_else.as_ref() {
+        if let Some(rule) = self.no_unused_imports.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14]));
             }
         }
-        if let Some(rule) = self.no_useless_lone_block_statements.as_ref() {
+        if let Some(rule) = self.no_useless_else.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[15]));
             }
         }
-        if let Some(rule) = self.no_void.as_ref() {
+        if let Some(rule) = self.no_useless_lone_block_statements.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16]));
             }
         }
-        if let Some(rule) = self.use_aria_activedescendant_with_tabindex.as_ref() {
+        if let Some(rule) = self.no_void.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17]));
             }
         }
-        if let Some(rule) = self.use_arrow_function.as_ref() {
+        if let Some(rule) = self.use_aria_activedescendant_with_tabindex.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18]));
             }
         }
-        if let Some(rule) = self.use_as_const_assertion.as_ref() {
+        if let Some(rule) = self.use_arrow_function.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19]));
             }
         }
-        if let Some(rule) = self.use_collapsed_else_if.as_ref() {
+        if let Some(rule) = self.use_as_const_assertion.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20]));
             }
         }
-        if let Some(rule) = self.use_exhaustive_dependencies.as_ref() {
+        if let Some(rule) = self.use_collapsed_else_if.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21]));
             }
         }
-        if let Some(rule) = self.use_grouped_type_import.as_ref() {
+        if let Some(rule) = self.use_exhaustive_dependencies.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22]));
             }
         }
-        if let Some(rule) = self.use_hook_at_top_level.as_ref() {
+        if let Some(rule) = self.use_grouped_type_import.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23]));
             }
         }
-        if let Some(rule) = self.use_import_restrictions.as_ref() {
+        if let Some(rule) = self.use_hook_at_top_level.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24]));
             }
         }
-        if let Some(rule) = self.use_is_array.as_ref() {
+        if let Some(rule) = self.use_import_restrictions.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25]));
             }
         }
-        if let Some(rule) = self.use_shorthand_assign.as_ref() {
+        if let Some(rule) = self.use_is_array.as_ref() {
             if rule.is_enabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26]));
             }
         }
+        if let Some(rule) = self.use_shorthand_assign.as_ref() {
+            if rule.is_enabled() {
+                index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27]));
+            }
+        }
         index_set
     }
     pub(crate) fn get_disabled_rules(&self) -> IndexSet<RuleFilter> {
@@ -2604,121 +2620,126 @@ impl Nursery {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[3]));
             }
         }
-        if let Some(rule) = self.no_empty_character_class_in_regex.as_ref() {
+        if let Some(rule) = self.no_empty_block_statements.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[4]));
             }
         }
-        if let Some(rule) = self.no_excessive_complexity.as_ref() {
+        if let Some(rule) = self.no_empty_character_class_in_regex.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[5]));
             }
         }
-        if let Some(rule) = self.no_fallthrough_switch_clause.as_ref() {
+        if let Some(rule) = self.no_excessive_complexity.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[6]));
             }
         }
-        if let Some(rule) = self.no_global_is_finite.as_ref() {
+        if let Some(rule) = self.no_fallthrough_switch_clause.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[7]));
             }
         }
-        if let Some(rule) = self.no_global_is_nan.as_ref() {
+        if let Some(rule) = self.no_global_is_finite.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[8]));
             }
         }
-        if let Some(rule) = self.no_interactive_element_to_noninteractive_role.as_ref() {
+        if let Some(rule) = self.no_global_is_nan.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[9]));
             }
         }
-        if let Some(rule) = self.no_invalid_new_builtin.as_ref() {
+        if let Some(rule) = self.no_interactive_element_to_noninteractive_role.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[10]));
             }
         }
-        if let Some(rule) = self.no_misleading_instantiator.as_ref() {
+        if let Some(rule) = self.no_invalid_new_builtin.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[11]));
             }
         }
-        if let Some(rule) = self.no_misrefactored_shorthand_assign.as_ref() {
+        if let Some(rule) = self.no_misleading_instantiator.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[12]));
             }
         }
-        if let Some(rule) = self.no_unused_imports.as_ref() {
+        if let Some(rule) = self.no_misrefactored_shorthand_assign.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[13]));
             }
         }
-        if let Some(rule) = self.no_useless_else.as_ref() {
+        if let Some(rule) = self.no_unused_imports.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[14]));
             }
         }
-        if let Some(rule) = self.no_useless_lone_block_statements.as_ref() {
+        if let Some(rule) = self.no_useless_else.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[15]));
             }
         }
-        if let Some(rule) = self.no_void.as_ref() {
+        if let Some(rule) = self.no_useless_lone_block_statements.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[16]));
             }
         }
-        if let Some(rule) = self.use_aria_activedescendant_with_tabindex.as_ref() {
+        if let Some(rule) = self.no_void.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[17]));
             }
         }
-        if let Some(rule) = self.use_arrow_function.as_ref() {
+        if let Some(rule) = self.use_aria_activedescendant_with_tabindex.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[18]));
             }
         }
-        if let Some(rule) = self.use_as_const_assertion.as_ref() {
+        if let Some(rule) = self.use_arrow_function.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[19]));
             }
         }
-        if let Some(rule) = self.use_collapsed_else_if.as_ref() {
+        if let Some(rule) = self.use_as_const_assertion.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[20]));
             }
         }
-        if let Some(rule) = self.use_exhaustive_dependencies.as_ref() {
+        if let Some(rule) = self.use_collapsed_else_if.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[21]));
             }
         }
-        if let Some(rule) = self.use_grouped_type_import.as_ref() {
+        if let Some(rule) = self.use_exhaustive_dependencies.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[22]));
             }
         }
-        if let Some(rule) = self.use_hook_at_top_level.as_ref() {
+        if let Some(rule) = self.use_grouped_type_import.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[23]));
             }
         }
-        if let Some(rule) = self.use_import_restrictions.as_ref() {
+        if let Some(rule) = self.use_hook_at_top_level.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[24]));
             }
         }
-        if let Some(rule) = self.use_is_array.as_ref() {
+        if let Some(rule) = self.use_import_restrictions.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[25]));
             }
         }
-        if let Some(rule) = self.use_shorthand_assign.as_ref() {
+        if let Some(rule) = self.use_is_array.as_ref() {
             if rule.is_disabled() {
                 index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[26]));
             }
         }
+        if let Some(rule) = self.use_shorthand_assign.as_ref() {
+            if rule.is_disabled() {
+                index_set.insert(RuleFilter::Rule(Self::GROUP_NAME, Self::GROUP_RULES[27]));
+            }
+        }
         index_set
     }
     #[doc = r" Checks if, given a rule name, matches one of the rules contained in this category"]
@@ -2732,7 +2753,7 @@ impl Nursery {
     pub(crate) fn recommended_rules_as_filters() -> [RuleFilter<'static>; 12] {
         Self::RECOMMENDED_RULES_AS_FILTERS
     }
-    pub(crate) fn all_rules_as_filters() -> [RuleFilter<'static>; 27] {
+    pub(crate) fn all_rules_as_filters() -> [RuleFilter<'static>; 28] {
         Self::ALL_RULES_AS_FILTERS
     }
     #[doc = r" Select preset rules"]
@@ -2759,6 +2780,7 @@ impl Nursery {
             "noApproximativeNumericConstant" => self.no_approximative_numeric_constant.as_ref(),
             "noConfusingVoidType" => self.no_confusing_void_type.as_ref(),
             "noDuplicateJsonKeys" => self.no_duplicate_json_keys.as_ref(),
+            "noEmptyBlockStatements" => self.no_empty_block_statements.as_ref(),
             "noEmptyCharacterClassInRegex" => self.no_empty_character_class_in_regex.as_ref(),
             "noExcessiveComplexity" => self.no_excessive_complexity.as_ref(),
             "noFallthroughSwitchClause" => self.no_fallthrough_switch_clause.as_ref(),
diff --git a/crates/biome_service/src/configuration/parse/json/rules.rs b/crates/biome_service/src/configuration/parse/json/rules.rs
index 55ae32ece711..aa34a6dc57e4 100644
--- a/crates/biome_service/src/configuration/parse/json/rules.rs
+++ b/crates/biome_service/src/configuration/parse/json/rules.rs
@@ -2027,6 +2027,7 @@ impl VisitNode<JsonLanguage> for Nursery {
                 "noApproximativeNumericConstant",
                 "noConfusingVoidType",
                 "noDuplicateJsonKeys",
+                "noEmptyBlockStatements",
                 "noEmptyCharacterClassInRegex",
                 "noExcessiveComplexity",
                 "noFallthroughSwitchClause",
@@ -2161,6 +2162,29 @@ impl VisitNode<JsonLanguage> for Nursery {
                     ));
                 }
             },
+            "noEmptyBlockStatements" => match value {
+                AnyJsonValue::JsonStringValue(_) => {
+                    let mut configuration = RuleConfiguration::default();
+                    self.map_to_known_string(&value, name_text, &mut configuration, diagnostics)?;
+                    self.no_empty_block_statements = Some(configuration);
+                }
+                AnyJsonValue::JsonObjectValue(_) => {
+                    let mut rule_configuration = RuleConfiguration::default();
+                    rule_configuration.map_rule_configuration(
+                        &value,
+                        name_text,
+                        "noEmptyBlockStatements",
+                        diagnostics,
+                    )?;
+                    self.no_empty_block_statements = Some(rule_configuration);
+                }
+                _ => {
+                    diagnostics.push(DeserializationDiagnostic::new_incorrect_type(
+                        "object or string",
+                        value.range(),
+                    ));
+                }
+            },
             "noEmptyCharacterClassInRegex" => match value {
                 AnyJsonValue::JsonStringValue(_) => {
                     let mut configuration = RuleConfiguration::default();
diff --git a/editors/vscode/configuration_schema.json b/editors/vscode/configuration_schema.json
index 911a5b2ad25c..4f20250e6e8a 100644
--- a/editors/vscode/configuration_schema.json
+++ b/editors/vscode/configuration_schema.json
@@ -1026,6 +1026,13 @@
 						{ "type": "null" }
 					]
 				},
+				"noEmptyBlockStatements": {
+					"description": "Disallow empty block statements and static blocks.",
+					"anyOf": [
+						{ "$ref": "#/definitions/RuleConfiguration" },
+						{ "type": "null" }
+					]
+				},
 				"noEmptyCharacterClassInRegex": {
 					"description": "Disallow empty character classes in regular expression literals.",
 					"anyOf": [
diff --git a/packages/@biomejs/backend-jsonrpc/src/workspace.ts b/packages/@biomejs/backend-jsonrpc/src/workspace.ts
index 0841f4683206..d9c8b0a9f8c0 100644
--- a/packages/@biomejs/backend-jsonrpc/src/workspace.ts
+++ b/packages/@biomejs/backend-jsonrpc/src/workspace.ts
@@ -697,6 +697,10 @@ export interface Nursery {
 	 * Disallow two keys with the same name inside a JSON object.
 	 */
 	noDuplicateJsonKeys?: RuleConfiguration;
+	/**
+	 * Disallow empty block statements and static blocks.
+	 */
+	noEmptyBlockStatements?: RuleConfiguration;
 	/**
 	 * Disallow empty character classes in regular expression literals.
 	 */
@@ -1347,6 +1351,7 @@ export type Category =
 	| "lint/nursery/noApproximativeNumericConstant"
 	| "lint/nursery/noConfusingVoidType"
 	| "lint/nursery/noDuplicateJsonKeys"
+	| "lint/nursery/noEmptyBlockStatements"
 	| "lint/nursery/noEmptyCharacterClassInRegex"
 	| "lint/nursery/noExcessiveComplexity"
 	| "lint/nursery/noFallthroughSwitchClause"
diff --git a/packages/@biomejs/biome/configuration_schema.json b/packages/@biomejs/biome/configuration_schema.json
index 911a5b2ad25c..4f20250e6e8a 100644
--- a/packages/@biomejs/biome/configuration_schema.json
+++ b/packages/@biomejs/biome/configuration_schema.json
@@ -1026,6 +1026,13 @@
 						{ "type": "null" }
 					]
 				},
+				"noEmptyBlockStatements": {
+					"description": "Disallow empty block statements and static blocks.",
+					"anyOf": [
+						{ "$ref": "#/definitions/RuleConfiguration" },
+						{ "type": "null" }
+					]
+				},
 				"noEmptyCharacterClassInRegex": {
 					"description": "Disallow empty character classes in regular expression literals.",
 					"anyOf": [
diff --git a/website/src/components/generated/NumberOfRules.astro b/website/src/components/generated/NumberOfRules.astro
index 75b3faa7ebd5..6b9300bc0694 100644
--- a/website/src/components/generated/NumberOfRules.astro
+++ b/website/src/components/generated/NumberOfRules.astro
@@ -1,2 +1,2 @@
 <!-- this file is auto generated, use `cargo lintdoc` to update it -->
- <p>Biome's linter has a total of <strong><a href='/linter/rules'>169 rules</a></strong><p>
\ No newline at end of file
+ <p>Biome's linter has a total of <strong><a href='/linter/rules'>170 rules</a></strong><p>
\ No newline at end of file
diff --git a/website/src/content/docs/linter/rules/index.mdx b/website/src/content/docs/linter/rules/index.mdx
index 741148fac47c..a2e02d15af7c 100644
--- a/website/src/content/docs/linter/rules/index.mdx
+++ b/website/src/content/docs/linter/rules/index.mdx
@@ -208,6 +208,7 @@ Rules that belong to this group <strong>are not subject to semantic version</str
 | [noApproximativeNumericConstant](/linter/rules/no-approximative-numeric-constant) | Usually, the definition in the standard library is more precise than what people come up with or the used constant exceeds the maximum precision of the number type. |  |
 | [noConfusingVoidType](/linter/rules/no-confusing-void-type) | Disallow <code>void</code> type outside of generic or return types. |  |
 | [noDuplicateJsonKeys](/linter/rules/no-duplicate-json-keys) | Disallow two keys with the same name inside a JSON object. |  |
+| [noEmptyBlockStatements](/linter/rules/no-empty-block-statements) | Disallow empty block statements and static blocks. |  |
 | [noEmptyCharacterClassInRegex](/linter/rules/no-empty-character-class-in-regex) | Disallow empty character classes in regular expression literals. |  |
 | [noExcessiveComplexity](/linter/rules/no-excessive-complexity) | Disallow functions that exceed a given Cognitive Complexity score. |  |
 | [noFallthroughSwitchClause](/linter/rules/no-fallthrough-switch-clause) | Disallow fallthrough of <code>switch</code> clauses. |  |
diff --git a/website/src/content/docs/linter/rules/no-empty-block-statements.md b/website/src/content/docs/linter/rules/no-empty-block-statements.md
new file mode 100644
index 000000000000..8e67c4c2f7d1
--- /dev/null
+++ b/website/src/content/docs/linter/rules/no-empty-block-statements.md
@@ -0,0 +1,105 @@
+---
+title: noEmptyBlockStatements (since vnext)
+---
+
+**Diagnostic Category: `lint/nursery/noEmptyBlockStatements`**
+
+:::caution
+This rule is part of the [nursery](/linter/rules/#nursery) group.
+:::
+
+Disallow empty block statements and static blocks.
+
+Empty static blocks and block statements, while not technically errors, usually occur due to refactoring that wasn’t completed. They can cause confusion when reading code.
+
+This rule disallows empty block statements and static blocks.
+This rule ignores block statements or static blocks which contain a comment (for example, in an empty catch or finally block of a try statement to indicate that execution should continue regardless of errors).
+
+Source: https://eslint.org/docs/latest/rules/no-empty-static-block/
+Source: https://eslint.org/docs/latest/rules/no-empty/
+
+## Examples
+
+### Invalid
+
+```jsx
+function emptyFunctionBody () {}
+```
+
+<pre class="language-text"><code class="language-text">nursery/noEmptyBlockStatements.js:1:31 <a href="https://biomejs.dev/lint/rules/no-empty-block-statements">lint/nursery/noEmptyBlockStatements</a> ━━━━━━━━━━━━━━━━━━━━━━━━━
+
+<strong><span style="color: Orange;">  </span></strong><strong><span style="color: Orange;">⚠</span></strong> <span style="color: Orange;">Unexpected empty block.</span>
+  
+<strong><span style="color: Tomato;">  </span></strong><strong><span style="color: Tomato;">&gt;</span></strong> <strong>1 │ </strong>function emptyFunctionBody () {}
+   <strong>   │ </strong>                              <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong>
+    <strong>2 │ </strong>
+  
+<strong><span style="color: lightgreen;">  </span></strong><strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.</span>
+  
+</code></pre>
+
+```jsx
+try {
+    doSomething();
+} catch(ex) {
+
+}
+```
+
+<pre class="language-text"><code class="language-text">nursery/noEmptyBlockStatements.js:3:13 <a href="https://biomejs.dev/lint/rules/no-empty-block-statements">lint/nursery/noEmptyBlockStatements</a> ━━━━━━━━━━━━━━━━━━━━━━━━━
+
+<strong><span style="color: Orange;">  </span></strong><strong><span style="color: Orange;">⚠</span></strong> <span style="color: Orange;">Unexpected empty block.</span>
+  
+    <strong>1 │ </strong>try {
+    <strong>2 │ </strong>    doSomething();
+<strong><span style="color: Tomato;">  </span></strong><strong><span style="color: Tomato;">&gt;</span></strong> <strong>3 │ </strong>} catch(ex) {
+   <strong>   │ </strong>            <strong><span style="color: Tomato;">^</span></strong>
+<strong><span style="color: Tomato;">  </span></strong><strong><span style="color: Tomato;">&gt;</span></strong> <strong>4 │ </strong>
+<strong><span style="color: Tomato;">  </span></strong><strong><span style="color: Tomato;">&gt;</span></strong> <strong>5 │ </strong>}
+   <strong>   │ </strong><strong><span style="color: Tomato;">^</span></strong>
+    <strong>6 │ </strong>
+  
+<strong><span style="color: lightgreen;">  </span></strong><strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.</span>
+  
+</code></pre>
+
+```jsx
+class Foo {
+  static {}
+}
+```
+
+<pre class="language-text"><code class="language-text">nursery/noEmptyBlockStatements.js:2:3 <a href="https://biomejs.dev/lint/rules/no-empty-block-statements">lint/nursery/noEmptyBlockStatements</a> ━━━━━━━━━━━━━━━━━━━━━━━━━━
+
+<strong><span style="color: Orange;">  </span></strong><strong><span style="color: Orange;">⚠</span></strong> <span style="color: Orange;">Unexpected empty block.</span>
+  
+    <strong>1 │ </strong>class Foo {
+<strong><span style="color: Tomato;">  </span></strong><strong><span style="color: Tomato;">&gt;</span></strong> <strong>2 │ </strong>  static {}
+   <strong>   │ </strong>  <strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong><strong><span style="color: Tomato;">^</span></strong>
+    <strong>3 │ </strong>}
+    <strong>4 │ </strong>
+  
+<strong><span style="color: lightgreen;">  </span></strong><strong><span style="color: lightgreen;">ℹ</span></strong> <span style="color: lightgreen;">Empty blocks are usually the result of an incomplete refactoring. Remove the empty block or add a comment inside it if it is intentional.</span>
+  
+</code></pre>
+
+## Valid
+
+```jsx
+function foo () {
+    doSomething();
+}
+```
+
+```jsx
+try {
+  doSomething();
+} catch (ex) {
+  // continue regardless of error
+}
+```
+
+## Related links
+
+- [Disable a rule](/linter/#disable-a-lint-rule)
+- [Rule options](/linter/#rule-options)