diff --git a/CHANGELOG.md b/CHANGELOG.md
index df696b313ca1..50486755eb58 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -30,6 +30,7 @@
 
 ### Chore & Maintenance
 
+- `[jest-changed-files, jest-circus, jest-console, @jest/core, @jest/runtime, @jest/transform]` Use `invariant` and `notEmpty` from `jest-util` rather than own internal ([#14366](https://github.com/jestjs/jest/pull/14366))
 - `[@jest/core]` Use `pluralize` from `jest-util` rather than own internal ([#14322](https://github.com/jestjs/jest/pull/14322))
 
 ## 29.6.1
diff --git a/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap b/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap
index 59acd31aae2f..0e49b62527c6 100644
--- a/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap
+++ b/e2e/__tests__/__snapshots__/circusDeclarationErrors.test.ts.snap
@@ -16,7 +16,7 @@ exports[`defining tests and hooks asynchronously throws 1`] = `
       14 |   });
       15 | });
 
-      at eventHandler (../../packages/jest-circus/build/eventHandler.js:140:11)
+      at eventHandler (../../packages/jest-circus/build/eventHandler.js:141:11)
       at test (__tests__/asyncDefinition.test.js:12:5)
 
   ● Test suite failed to run
@@ -31,7 +31,7 @@ exports[`defining tests and hooks asynchronously throws 1`] = `
       15 | });
       16 |
 
-      at eventHandler (../../packages/jest-circus/build/eventHandler.js:103:11)
+      at eventHandler (../../packages/jest-circus/build/eventHandler.js:104:11)
       at afterAll (__tests__/asyncDefinition.test.js:13:5)
 
   ● Test suite failed to run
@@ -46,7 +46,7 @@ exports[`defining tests and hooks asynchronously throws 1`] = `
       20 | });
       21 |
 
-      at eventHandler (../../packages/jest-circus/build/eventHandler.js:140:11)
+      at eventHandler (../../packages/jest-circus/build/eventHandler.js:141:11)
       at test (__tests__/asyncDefinition.test.js:18:3)
 
   ● Test suite failed to run
@@ -60,6 +60,6 @@ exports[`defining tests and hooks asynchronously throws 1`] = `
       20 | });
       21 |
 
-      at eventHandler (../../packages/jest-circus/build/eventHandler.js:103:11)
+      at eventHandler (../../packages/jest-circus/build/eventHandler.js:104:11)
       at afterAll (__tests__/asyncDefinition.test.js:19:3)"
 `;
diff --git a/packages/jest-changed-files/package.json b/packages/jest-changed-files/package.json
index a0a5c5cd1e25..6dda0ea22cb1 100644
--- a/packages/jest-changed-files/package.json
+++ b/packages/jest-changed-files/package.json
@@ -18,6 +18,7 @@
   },
   "dependencies": {
     "execa": "^5.0.0",
+    "jest-util": "workspace:^",
     "p-limit": "^3.1.0"
   },
   "engines": {
diff --git a/packages/jest-changed-files/src/index.ts b/packages/jest-changed-files/src/index.ts
index df3cb0723c34..3577d49e05ee 100644
--- a/packages/jest-changed-files/src/index.ts
+++ b/packages/jest-changed-files/src/index.ts
@@ -7,6 +7,7 @@
  */
 
 import pLimit = require('p-limit');
+import {isNonNullable} from 'jest-util';
 import git from './git';
 import hg from './hg';
 import sl from './sl';
@@ -16,10 +17,6 @@ type RootPromise = ReturnType<SCMAdapter['getRoot']>;
 
 export type {ChangedFiles, ChangedFilesPromise} from './types';
 
-function notEmpty<T>(value: T | null | undefined): value is T {
-  return value != null;
-}
-
 // This is an arbitrary number. The main goal is to prevent projects with
 // many roots (50+) from spawning too many processes at once.
 const mutex = pLimit(5);
@@ -78,8 +75,8 @@ export const findRepos = async (roots: Array<string>): Promise<Repos> => {
   const slRepos = await Promise.all(roots.map(findSlRoot));
 
   return {
-    git: new Set(gitRepos.filter(notEmpty)),
-    hg: new Set(hgRepos.filter(notEmpty)),
-    sl: new Set(slRepos.filter(notEmpty)),
+    git: new Set(gitRepos.filter(isNonNullable)),
+    hg: new Set(hgRepos.filter(isNonNullable)),
+    sl: new Set(slRepos.filter(isNonNullable)),
   };
 };
diff --git a/packages/jest-changed-files/tsconfig.json b/packages/jest-changed-files/tsconfig.json
index 12688a2879d6..aad1b761e910 100644
--- a/packages/jest-changed-files/tsconfig.json
+++ b/packages/jest-changed-files/tsconfig.json
@@ -4,5 +4,6 @@
     "rootDir": "src",
     "outDir": "build"
   },
-  "include": ["./src/**/*"]
+  "include": ["./src/**/*"],
+  "references": [{"path": "../jest-util"}]
 }
diff --git a/packages/jest-circus/src/eventHandler.ts b/packages/jest-circus/src/eventHandler.ts
index 0a437df1ed9a..4c401cada760 100644
--- a/packages/jest-circus/src/eventHandler.ts
+++ b/packages/jest-circus/src/eventHandler.ts
@@ -6,6 +6,7 @@
  */
 
 import type {Circus} from '@jest/types';
+import {invariant} from 'jest-util';
 import {
   injectGlobalErrorHandlers,
   restoreGlobalErrorHandlers,
@@ -15,7 +16,6 @@ import {
   addErrorToEachTestUnderDescribe,
   describeBlockHasTests,
   getTestDuration,
-  invariant,
   makeDescribe,
   makeTest,
 } from './utils';
diff --git a/packages/jest-circus/src/run.ts b/packages/jest-circus/src/run.ts
index 02766579678f..eac6a20b06e6 100644
--- a/packages/jest-circus/src/run.ts
+++ b/packages/jest-circus/src/run.ts
@@ -9,6 +9,7 @@ import {AsyncLocalStorage} from 'async_hooks';
 import pLimit = require('p-limit');
 import {jestExpect} from '@jest/expect';
 import type {Circus} from '@jest/types';
+import {invariant} from 'jest-util';
 import shuffleArray, {RandomNumberGenerator, rngBuilder} from './shuffleArray';
 import {dispatch, getState} from './state';
 import {RETRY_TIMES} from './types';
@@ -17,7 +18,6 @@ import {
   getAllHooksForDescribe,
   getEachHooksForTest,
   getTestID,
-  invariant,
   makeRunResult,
 } from './utils';
 
diff --git a/packages/jest-circus/src/utils.ts b/packages/jest-circus/src/utils.ts
index 9e1c8d74838b..fa45f4fbb744 100644
--- a/packages/jest-circus/src/utils.ts
+++ b/packages/jest-circus/src/utils.ts
@@ -17,6 +17,7 @@ import {
   ErrorWithStack,
   convertDescriptorToString,
   formatTime,
+  invariant,
   isPromise,
 } from 'jest-util';
 import {format as prettyFormat} from 'pretty-format';
@@ -456,15 +457,6 @@ export const addErrorToEachTestUnderDescribe = (
   }
 };
 
-export function invariant(
-  condition: unknown,
-  message?: string,
-): asserts condition {
-  if (!condition) {
-    throw new Error(message);
-  }
-}
-
 type TestDescription = {
   ancestorTitles: Array<string>;
   fullName: string;
diff --git a/packages/jest-console/src/BufferedConsole.ts b/packages/jest-console/src/BufferedConsole.ts
index 526d51c38fdf..2ab7d73688ed 100644
--- a/packages/jest-console/src/BufferedConsole.ts
+++ b/packages/jest-console/src/BufferedConsole.ts
@@ -9,7 +9,7 @@ import {AssertionError, strict as assert} from 'assert';
 import {Console} from 'console';
 import {InspectOptions, format, formatWithOptions, inspect} from 'util';
 import chalk = require('chalk');
-import {ErrorWithStack, formatTime} from 'jest-util';
+import {ErrorWithStack, formatTime, invariant} from 'jest-util';
 import type {
   ConsoleBuffer,
   LogCounters,
@@ -180,9 +180,3 @@ export default class BufferedConsole extends Console {
     return this._buffer.length ? this._buffer : undefined;
   }
 }
-
-function invariant(condition: boolean, message?: string): asserts condition {
-  if (!condition) {
-    throw new Error(message);
-  }
-}
diff --git a/packages/jest-core/src/TestScheduler.ts b/packages/jest-core/src/TestScheduler.ts
index 2c53db5a41fc..77caa9a95c3f 100644
--- a/packages/jest-core/src/TestScheduler.ts
+++ b/packages/jest-core/src/TestScheduler.ts
@@ -38,7 +38,7 @@ import {
   buildSnapshotResolver,
   cleanup as cleanupSnapshots,
 } from 'jest-snapshot';
-import {ErrorWithStack, requireOrImportModule} from 'jest-util';
+import {ErrorWithStack, invariant, requireOrImportModule} from 'jest-util';
 import type {TestWatcher} from 'jest-watcher';
 import ReporterDispatcher from './ReporterDispatcher';
 import {shouldRunInBand} from './testSchedulerHelper';
@@ -425,12 +425,6 @@ class TestScheduler {
   }
 }
 
-function invariant(condition: unknown, message?: string): asserts condition {
-  if (!condition) {
-    throw new Error(message);
-  }
-}
-
 const createAggregatedResults = (numTotalTestSuites: number) => {
   const result = makeEmptyAggregatedTestResult();
   result.numTotalTestSuites = numTotalTestSuites;
diff --git a/packages/jest-core/src/lib/watchPluginsHelpers.ts b/packages/jest-core/src/lib/watchPluginsHelpers.ts
index 08cf4cae06ad..0479f544beb4 100644
--- a/packages/jest-core/src/lib/watchPluginsHelpers.ts
+++ b/packages/jest-core/src/lib/watchPluginsHelpers.ts
@@ -6,6 +6,7 @@
  */
 
 import type {Config} from '@jest/types';
+import {isNonNullable} from 'jest-util';
 import type {UsageData, WatchPlugin} from 'jest-watcher';
 
 export const filterInteractivePlugins = (
@@ -27,10 +28,6 @@ export const filterInteractivePlugins = (
   });
 };
 
-function notEmpty<T>(value: T | null | undefined): value is T {
-  return value != null;
-}
-
 export const getSortedUsageRows = (
   watchPlugins: Array<WatchPlugin>,
   globalConfig: Config.GlobalConfig,
@@ -56,4 +53,4 @@ export const getSortedUsageRows = (
       return 0;
     })
     .map(p => p.getUsageInfo && p.getUsageInfo(globalConfig))
-    .filter(notEmpty);
+    .filter(isNonNullable);
diff --git a/packages/jest-haste-map/src/index.ts b/packages/jest-haste-map/src/index.ts
index 5012d6ef1af5..37d7c0e2b171 100644
--- a/packages/jest-haste-map/src/index.ts
+++ b/packages/jest-haste-map/src/index.ts
@@ -13,7 +13,7 @@ import {deserialize, serialize} from 'v8';
 import {Stats, readFileSync, writeFileSync} from 'graceful-fs';
 import type {Config} from '@jest/types';
 import {escapePathForRegex} from 'jest-regex-util';
-import {requireOrImportModule} from 'jest-util';
+import {invariant, requireOrImportModule} from 'jest-util';
 import {JestWorkerFarm, Worker} from 'jest-worker';
 import HasteFS from './HasteFS';
 import HasteModuleMap from './ModuleMap';
@@ -131,12 +131,6 @@ const VCS_DIRECTORIES = ['.git', '.hg', '.sl']
   .map(vcs => escapePathForRegex(path.sep + vcs + path.sep))
   .join('|');
 
-function invariant(condition: unknown, message?: string): asserts condition {
-  if (!condition) {
-    throw new Error(message);
-  }
-}
-
 /**
  * HasteMap is a JavaScript implementation of Facebook's haste module system.
  *
diff --git a/packages/jest-runtime/src/index.ts b/packages/jest-runtime/src/index.ts
index d54ed63fb325..9b5647215101 100644
--- a/packages/jest-runtime/src/index.ts
+++ b/packages/jest-runtime/src/index.ts
@@ -53,7 +53,12 @@ import type {MockMetadata, ModuleMocker} from 'jest-mock';
 import {escapePathForRegex} from 'jest-regex-util';
 import Resolver, {ResolveModuleConfig} from 'jest-resolve';
 import {EXTENSION as SnapshotExtension} from 'jest-snapshot';
-import {createDirectory, deepCyclicCopy} from 'jest-util';
+import {
+  createDirectory,
+  deepCyclicCopy,
+  invariant,
+  isNonNullable,
+} from 'jest-util';
 import {
   createOutsideJestVmPath,
   decodePossibleOutsideJestVmPath,
@@ -1587,7 +1592,7 @@ export default class Runtime {
         module.path, // __dirname
         module.filename, // __filename
         lastArgs[0],
-        ...lastArgs.slice(1).filter(notEmpty),
+        ...lastArgs.slice(1).filter(isNonNullable),
       );
     } catch (error: any) {
       this.handleExecutionError(error, module);
@@ -2434,7 +2439,7 @@ export default class Runtime {
       '__filename',
       this._config.injectGlobals ? 'jest' : undefined,
       ...this._config.sandboxInjectedGlobals,
-    ].filter(notEmpty);
+    ].filter(isNonNullable);
   }
 
   private handleExecutionError(e: Error, module: Module): never {
@@ -2546,16 +2551,6 @@ export default class Runtime {
   }
 }
 
-function invariant(condition: unknown, message?: string): asserts condition {
-  if (!condition) {
-    throw new Error(message);
-  }
-}
-
-function notEmpty<T>(value: T | null | undefined): value is T {
-  return value !== null && value !== undefined;
-}
-
 async function evaluateSyntheticModule(module: SyntheticModule) {
   await module.link(() => {
     throw new Error('This should never happen');
diff --git a/packages/jest-transform/src/ScriptTransformer.ts b/packages/jest-transform/src/ScriptTransformer.ts
index 6728407dfcb9..8ee6aa12d8f1 100644
--- a/packages/jest-transform/src/ScriptTransformer.ts
+++ b/packages/jest-transform/src/ScriptTransformer.ts
@@ -20,6 +20,7 @@ import type {Config} from '@jest/types';
 import HasteMap from 'jest-haste-map';
 import {
   createDirectory,
+  invariant,
   isPromise,
   requireOrImportModule,
   tryRealpath,
@@ -1034,12 +1035,6 @@ const calcTransformRegExp = (config: Config.ProjectConfig) => {
   return transformRegexp;
 };
 
-function invariant(condition: unknown, message?: string): asserts condition {
-  if (condition == null || condition === false || condition === '') {
-    throw new Error(message);
-  }
-}
-
 function assertSyncTransformer(
   transformer: Transformer,
   name: string | undefined,
diff --git a/packages/jest-util/src/index.ts b/packages/jest-util/src/index.ts
index 1e73c92e0d18..531acfe4aa3a 100644
--- a/packages/jest-util/src/index.ts
+++ b/packages/jest-util/src/index.ts
@@ -28,3 +28,5 @@ export {default as pluralize} from './pluralize';
 export {default as formatTime} from './formatTime';
 export {default as tryRealpath} from './tryRealpath';
 export {default as requireOrImportModule} from './requireOrImportModule';
+export {default as invariant} from './invariant';
+export {default as isNonNullable} from './isNonNullable';
diff --git a/packages/jest-util/src/invariant.ts b/packages/jest-util/src/invariant.ts
new file mode 100644
index 000000000000..2e86440ae791
--- /dev/null
+++ b/packages/jest-util/src/invariant.ts
@@ -0,0 +1,15 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+export default function invariant(
+  condition: unknown,
+  message = '',
+): asserts condition {
+  if (!condition) {
+    throw new Error(message);
+  }
+}
diff --git a/packages/jest-util/src/isNonNullable.ts b/packages/jest-util/src/isNonNullable.ts
new file mode 100644
index 000000000000..34eddf095ef5
--- /dev/null
+++ b/packages/jest-util/src/isNonNullable.ts
@@ -0,0 +1,10 @@
+/**
+ * Copyright (c) Meta Platforms, Inc. and affiliates.
+ *
+ * This source code is licensed under the MIT license found in the
+ * LICENSE file in the root directory of this source tree.
+ */
+
+export default function isNonNullable<T>(value: T): value is NonNullable<T> {
+  return value != null;
+}
diff --git a/yarn.lock b/yarn.lock
index 68ff4925f6ec..a83a4736f19b 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -12347,6 +12347,7 @@ __metadata:
   resolution: "jest-changed-files@workspace:packages/jest-changed-files"
   dependencies:
     execa: ^5.0.0
+    jest-util: "workspace:^"
     p-limit: ^3.1.0
   languageName: unknown
   linkType: soft