diff --git a/lib/manager/gradle/shallow/__fixtures__/2/libs.versions.toml b/lib/manager/gradle/shallow/__fixtures__/2/libs.versions.toml
index 8308a0c81674fa228b7124ee93f5086ed25eaef6..85bad73700c60adeb0359743d00bffde04d6b219 100644
--- a/lib/manager/gradle/shallow/__fixtures__/2/libs.versions.toml
+++ b/lib/manager/gradle/shallow/__fixtures__/2/libs.versions.toml
@@ -7,6 +7,9 @@ okHttp = "com.squareup.okhttp3:okhttp:4.9.0"
 okio = { module = "com.squareup.okio:okio", version = "2.8.0" }
 picasso = { group = "com.squareup.picasso", name = "picasso", version = "2.5.1" }
 retrofit2-retrofit = { module = "com.squareup.retrofit2:retrofit", version.ref = "retrofit" }
+google-firebase-analytics = { module = "com.google.firebase:firebase-analytics" }
+google-firebase-crashlytics = { group = "com.google.firebase", name = "firebase-crashlytics" }
+google-firebase-messaging = "com.google.firebase:firebase-messaging"
 
 [plugins]
 kotlinJvm = { id = "org.jetbrains.kotlin.jvm", version = "1.5.21" }
diff --git a/lib/manager/gradle/shallow/extract.spec.ts b/lib/manager/gradle/shallow/extract.spec.ts
index e070e7371feef388350e7978bf1726b6c5ee02c9..33678e57c896c9442ded18aefc4f847d78a9f952 100644
--- a/lib/manager/gradle/shallow/extract.spec.ts
+++ b/lib/manager/gradle/shallow/extract.spec.ts
@@ -1,5 +1,6 @@
 import { extractAllPackageFiles } from '..';
 import { fs, loadFixture } from '../../../../test/util';
+import type { ExtractConfig } from '../../types';
 
 jest.mock('../../../util/fs');
 
@@ -24,7 +25,7 @@ describe('manager/gradle/shallow/extract', () => {
       'build.gradle': '',
     });
 
-    const res = await extractAllPackageFiles({} as never, [
+    const res = await extractAllPackageFiles({} as ExtractConfig, [
       'build.gradle',
       'gradle.properties',
     ]);
@@ -39,7 +40,7 @@ describe('manager/gradle/shallow/extract', () => {
       'settings.gradle': null,
     });
 
-    const res = await extractAllPackageFiles({} as never, [
+    const res = await extractAllPackageFiles({} as ExtractConfig, [
       'build.gradle',
       'gradle.properties',
       'settings.gradle',
@@ -75,7 +76,7 @@ describe('manager/gradle/shallow/extract', () => {
       'settings.gradle': null,
     });
 
-    const res = await extractAllPackageFiles({} as never, [
+    const res = await extractAllPackageFiles({} as ExtractConfig, [
       'build.gradle',
       'gradle.properties',
       'settings.gradle',
@@ -114,7 +115,7 @@ describe('manager/gradle/shallow/extract', () => {
       'settings.gradle': null,
     });
 
-    const res = await extractAllPackageFiles({} as never, [
+    const res = await extractAllPackageFiles({} as ExtractConfig, [
       'build.gradle',
       'gradle.properties',
       'settings.gradle',
@@ -156,7 +157,10 @@ describe('manager/gradle/shallow/extract', () => {
 
     mockFs(fsMock);
 
-    const res = await extractAllPackageFiles({} as never, Object.keys(fsMock));
+    const res = await extractAllPackageFiles(
+      {} as ExtractConfig,
+      Object.keys(fsMock)
+    );
 
     expect(res).toMatchObject([
       { packageFile: 'gradle.properties', deps: [] },
@@ -187,7 +191,10 @@ describe('manager/gradle/shallow/extract', () => {
 
     mockFs(fsMock);
 
-    const res = await extractAllPackageFiles({} as never, Object.keys(fsMock));
+    const res = await extractAllPackageFiles(
+      {} as ExtractConfig,
+      Object.keys(fsMock)
+    );
 
     expect(res).toMatchObject([
       {
@@ -218,7 +225,10 @@ describe('manager/gradle/shallow/extract', () => {
       'gradle/libs.versions.toml': tomlFile,
     };
     mockFs(fsMock);
-    const res = await extractAllPackageFiles({} as never, Object.keys(fsMock));
+    const res = await extractAllPackageFiles(
+      {} as ExtractConfig,
+      Object.keys(fsMock)
+    );
     expect(res).toMatchObject([
       {
         packageFile: 'gradle/libs.versions.toml',
@@ -302,7 +312,10 @@ describe('manager/gradle/shallow/extract', () => {
       'gradle/libs.versions.toml': tomlFile,
     };
     mockFs(fsMock);
-    const res = await extractAllPackageFiles({} as never, Object.keys(fsMock));
+    const res = await extractAllPackageFiles(
+      {} as ExtractConfig,
+      Object.keys(fsMock)
+    );
     expect(res).toMatchObject([
       {
         packageFile: 'gradle/libs.versions.toml',
@@ -343,6 +356,27 @@ describe('manager/gradle/shallow/extract', () => {
               packageFile: 'gradle/libs.versions.toml',
             },
           },
+          {
+            depName: 'google-firebase-analytics',
+            managerData: {
+              packageFile: 'gradle/libs.versions.toml',
+            },
+            skipReason: 'no-version',
+          },
+          {
+            depName: 'google-firebase-crashlytics',
+            managerData: {
+              packageFile: 'gradle/libs.versions.toml',
+            },
+            skipReason: 'no-version',
+          },
+          {
+            depName: 'google-firebase-messaging',
+            managerData: {
+              packageFile: 'gradle/libs.versions.toml',
+            },
+            skipReason: 'no-version',
+          },
           {
             depName: 'org.jetbrains.kotlin.jvm',
             depType: 'plugin',
@@ -351,7 +385,7 @@ describe('manager/gradle/shallow/extract', () => {
             lookupName:
               'org.jetbrains.kotlin.jvm:org.jetbrains.kotlin.jvm.gradle.plugin',
             managerData: {
-              fileReplacePosition: 415,
+              fileReplacePosition: 661,
               packageFile: 'gradle/libs.versions.toml',
             },
             registryUrls: [
@@ -386,7 +420,10 @@ describe('manager/gradle/shallow/extract', () => {
       'gradle/libs.versions.toml': tomlFile,
     };
     mockFs(fsMock);
-    const res = await extractAllPackageFiles({} as never, Object.keys(fsMock));
+    const res = await extractAllPackageFiles(
+      {} as ExtractConfig,
+      Object.keys(fsMock)
+    );
     expect(res).toBeNull();
   });
 });
diff --git a/lib/manager/gradle/shallow/extract.ts b/lib/manager/gradle/shallow/extract.ts
index cd9a3161f800a5234a13dc6d8b59e3f410aeb249..a89b590bd1cc2366316cf2d6993108db64a7a93e 100644
--- a/lib/manager/gradle/shallow/extract.ts
+++ b/lib/manager/gradle/shallow/extract.ts
@@ -67,12 +67,8 @@ export async function extractAllPackageFiles(
         updateVars(vars);
         extractedDeps.push(...deps);
       } else if (isTOMLFile(packageFile)) {
-        try {
-          const updatesFromCatalog = parseCatalog(packageFile, content);
-          extractedDeps.push(...updatesFromCatalog);
-        } catch (error) {
-          logger.warn({ error }, 'TOML parsing error');
-        }
+        const updatesFromCatalog = parseCatalog(packageFile, content);
+        extractedDeps.push(...updatesFromCatalog);
       } else if (isGradleFile(packageFile)) {
         const vars = getVars(registry, dir);
         const {
@@ -89,9 +85,9 @@ export async function extractAllPackageFiles(
         updateVars(gradleVars);
         extractedDeps.push(...deps);
       }
-    } catch (e) {
+    } catch (err) {
       logger.warn(
-        { config, packageFile },
+        { err, config, packageFile },
         `Failed to process Gradle file: ${packageFile}`
       );
     }
diff --git a/lib/manager/gradle/shallow/extract/catalog.ts b/lib/manager/gradle/shallow/extract/catalog.ts
index 0812932b95731cbe056b8b12f59ae38c97ccf143..89200c8f829acf55d9235ded996fdeebcf89dd88 100644
--- a/lib/manager/gradle/shallow/extract/catalog.ts
+++ b/lib/manager/gradle/shallow/extract/catalog.ts
@@ -1,7 +1,15 @@
 import { parse } from '@iarna/toml';
-import { PackageDependency } from '../../../types';
-import { GradleManagerData } from '../../types';
-import type { GradleCatalog, GradleCatalogPluginDescriptor } from '../types';
+import deepmerge from 'deepmerge';
+import { SkipReason } from '../../../../types';
+import { hasKey } from '../../../../util/object';
+import type { PackageDependency } from '../../../types';
+import type { GradleManagerData } from '../../types';
+import type {
+  GradleCatalog,
+  GradleCatalogArtifactDescriptor,
+  GradleCatalogModuleDescriptor,
+  VersionPointer,
+} from '../types';
 
 function findIndexAfter(
   content: string,
@@ -12,6 +20,123 @@ function findIndexAfter(
   return slicePoint + content.slice(slicePoint).indexOf(find);
 }
 
+function isArtifactDescriptor(
+  obj: GradleCatalogArtifactDescriptor | GradleCatalogModuleDescriptor
+): obj is GradleCatalogArtifactDescriptor {
+  return hasKey('group', obj);
+}
+
+interface VersionExtract {
+  currentValue?: string;
+  fileReplacePosition?: number;
+}
+
+function extractVersion({
+  version,
+  versions,
+  depStartIndex,
+  depSubContent,
+  depName,
+  versionStartIndex,
+  versionSubContent,
+}: {
+  version: string | VersionPointer;
+  versions: Record<string, string>;
+  depStartIndex: number;
+  depSubContent: string;
+  depName: string;
+  versionStartIndex: number;
+  versionSubContent: string;
+}): VersionExtract {
+  if (!version) {
+    return {};
+  }
+  const currentValue =
+    typeof version === 'string' ? version : versions[version.ref];
+
+  const fileReplacePosition =
+    typeof version === 'string'
+      ? depStartIndex + findIndexAfter(depSubContent, depName, currentValue)
+      : versionStartIndex +
+        findIndexAfter(versionSubContent, version.ref, currentValue);
+  return { currentValue, fileReplacePosition };
+}
+
+function extractDependency({
+  descriptor,
+  versions,
+  depStartIndex,
+  depSubContent,
+  depName,
+  versionStartIndex,
+  versionSubContent,
+}: {
+  descriptor:
+    | string
+    | GradleCatalogModuleDescriptor
+    | GradleCatalogArtifactDescriptor;
+  versions: Record<string, string>;
+  depStartIndex: number;
+  depSubContent: string;
+  depName: string;
+  versionStartIndex: number;
+  versionSubContent: string;
+}): PackageDependency<GradleManagerData> {
+  if (typeof descriptor === 'string') {
+    const [groupName, name, currentValue] = descriptor.split(':');
+    if (!currentValue) {
+      return {
+        depName,
+        skipReason: SkipReason.NoVersion,
+      };
+    }
+    return {
+      depName: `${groupName}:${name}`,
+      groupName,
+      currentValue,
+      managerData: {
+        fileReplacePosition:
+          depStartIndex + findIndexAfter(depSubContent, depName, currentValue),
+      },
+    };
+  }
+
+  const { currentValue, fileReplacePosition } = extractVersion({
+    version: descriptor.version,
+    versions,
+    depStartIndex,
+    depSubContent,
+    depName,
+    versionStartIndex,
+    versionSubContent,
+  });
+
+  if (!currentValue) {
+    return {
+      depName,
+      skipReason: SkipReason.NoVersion,
+    };
+  }
+
+  if (isArtifactDescriptor(descriptor)) {
+    const { group: groupName, name } = descriptor;
+    return {
+      depName: `${groupName}:${name}`,
+      groupName,
+      currentValue,
+      managerData: { fileReplacePosition },
+    };
+  }
+  const [groupName, name] = descriptor.module.split(':');
+  const dependency = {
+    depName: `${groupName}:${name}`,
+    groupName,
+    currentValue,
+    managerData: { fileReplacePosition },
+  };
+  return dependency;
+}
+
 export function parseCatalog(
   packageFile: string,
   content: string
@@ -26,58 +151,46 @@ export function parseCatalog(
   const extractedDeps: PackageDependency<GradleManagerData>[] = [];
   for (const libraryName of Object.keys(libs)) {
     const libDescriptor = libs[libraryName];
-    const group: string =
-      typeof libDescriptor === 'string'
-        ? libDescriptor.split(':')[0]
-        : libDescriptor.group || libDescriptor.module?.split(':')[0];
-    const name: string =
-      typeof libDescriptor === 'string'
-        ? libDescriptor.split(':')[1]
-        : libDescriptor.name || libDescriptor.module?.split(':')[1];
-    const version = libDescriptor.version || libDescriptor.split(':')[2];
-    const currentVersion =
-      typeof version === 'string' ? version : versions[version.ref];
-    const fileReplacePosition =
-      typeof version === 'string'
-        ? libStartIndex +
-          findIndexAfter(libSubContent, libraryName, currentVersion)
-        : versionStartIndex +
-          findIndexAfter(versionSubContent, version.ref, currentVersion);
-    const dependency = {
-      depName: `${group}:${name}`,
-      groupName: group,
-      currentValue: currentVersion,
-      managerData: { fileReplacePosition, packageFile },
-    };
+    const dependency = extractDependency({
+      descriptor: libDescriptor,
+      versions,
+      depStartIndex: libStartIndex,
+      depSubContent: libSubContent,
+      depName: libraryName,
+      versionStartIndex,
+      versionSubContent,
+    });
     extractedDeps.push(dependency);
   }
+
   const plugins = tomlContent.plugins || {};
   const pluginsStartIndex = content.indexOf('[plugins]');
   const pluginsSubContent = content.slice(pluginsStartIndex);
   for (const pluginName of Object.keys(plugins)) {
-    const pluginDescriptor = plugins[
-      pluginName
-    ] as GradleCatalogPluginDescriptor;
-    const pluginId = pluginDescriptor.id;
-    const version = pluginDescriptor.version;
-    const currentVersion: string =
-      typeof version === 'string' ? version : versions[version.ref];
-    const fileReplacePosition =
-      typeof version === 'string'
-        ? pluginsStartIndex +
-          findIndexAfter(pluginsSubContent, pluginId, currentVersion)
-        : versionStartIndex +
-          findIndexAfter(versionSubContent, version.ref, currentVersion);
+    const pluginDescriptor = plugins[pluginName];
+    const depName = pluginDescriptor.id;
+    const { currentValue, fileReplacePosition } = extractVersion({
+      version: pluginDescriptor.version,
+      versions,
+      depStartIndex: pluginsStartIndex,
+      depSubContent: pluginsSubContent,
+      depName,
+      versionStartIndex,
+      versionSubContent,
+    });
+
     const dependency = {
       depType: 'plugin',
-      depName: pluginId,
-      lookupName: `${pluginId}:${pluginId}.gradle.plugin`,
+      depName,
+      lookupName: `${depName}:${depName}.gradle.plugin`,
       registryUrls: ['https://plugins.gradle.org/m2/'],
-      currentValue: currentVersion,
+      currentValue,
       commitMessageTopic: `plugin ${pluginName}`,
-      managerData: { fileReplacePosition, packageFile },
+      managerData: { fileReplacePosition },
     };
     extractedDeps.push(dependency);
   }
-  return extractedDeps;
+  return extractedDeps.map((dep) =>
+    deepmerge(dep, { managerData: { packageFile } })
+  );
 }
diff --git a/lib/manager/gradle/shallow/types.ts b/lib/manager/gradle/shallow/types.ts
index a1867f968ceaf0e4059fc898cb034ff658e54498..384f14a08d28a2d50f565bbfc1fba8cb064f8316 100644
--- a/lib/manager/gradle/shallow/types.ts
+++ b/lib/manager/gradle/shallow/types.ts
@@ -63,23 +63,23 @@ export interface ParseGradleResult {
 }
 
 export interface GradleCatalog {
-  versions?: Map<string, string>;
-  libraries?: Map<
+  versions?: Record<string, string>;
+  libraries?: Record<
     string,
     GradleCatalogModuleDescriptor | GradleCatalogArtifactDescriptor | string
   >;
-  plugins?: Map<string, GradleCatalogPluginDescriptor>;
+  plugins?: Record<string, GradleCatalogPluginDescriptor>;
 }
 
 export interface GradleCatalogModuleDescriptor {
   module: string;
-  version: string | VersionPointer;
+  version?: string | VersionPointer;
 }
 
 export interface GradleCatalogArtifactDescriptor {
   name: string;
   group: string;
-  version: string | VersionPointer;
+  version?: string | VersionPointer;
 }
 
 export interface GradleCatalogPluginDescriptor {
diff --git a/lib/manager/gradle/types.ts b/lib/manager/gradle/types.ts
index db9264e9240d49aecc3aacf05d66652174687305..915ce0da45f9d0b88f875f1405ebd13829ee5266 100644
--- a/lib/manager/gradle/types.ts
+++ b/lib/manager/gradle/types.ts
@@ -1,4 +1,4 @@
 export interface GradleManagerData {
-  fileReplacePosition: number;
+  fileReplacePosition?: number;
   packageFile?: string;
 }