diff --git a/lib/config/presets/npm/index.ts b/lib/config/presets/npm/index.ts
index 6c9b5cc508d51ae542a900d73d668d7a564d48f0..d78e5dd3b8628f0538a74f9dc9084cd39e5d536e 100644
--- a/lib/config/presets/npm/index.ts
+++ b/lib/config/presets/npm/index.ts
@@ -31,11 +31,11 @@ export async function getPreset({
       );
     }
     const body = (await http.getJson<NpmResponse>(packageUrl)).body;
-    dep = body.versions[body['dist-tags'].latest];
+    dep = body.versions[body['dist-tags']?.latest];
   } catch (err) {
     throw new Error(PRESET_DEP_NOT_FOUND);
   }
-  if (!dep['renovate-config']) {
+  if (!dep?.['renovate-config']) {
     throw new Error(PRESET_RENOVATE_CONFIG_NOT_FOUND);
   }
   const presetConfig = dep['renovate-config'][presetName];
diff --git a/lib/modules/datasource/npm/get.spec.ts b/lib/modules/datasource/npm/get.spec.ts
index 1c3dce29bef4ea7c886488f1285c5a64e8735f9a..179a7711b538a95eb345907f7f890a4314eba931 100644
--- a/lib/modules/datasource/npm/get.spec.ts
+++ b/lib/modules/datasource/npm/get.spec.ts
@@ -286,6 +286,27 @@ describe('modules/datasource/npm/get', () => {
     `);
   });
 
+  it('handles missing dist-tags latest', async () => {
+    setNpmrc('registry=https://test.org\n_authToken=XXX');
+
+    httpMock
+      .scope('https://test.org')
+      .get('/@neutrinojs%2Freact')
+      .reply(200, {
+        name: '@neutrinojs/react',
+        repository: {
+          type: 'git',
+          url: 'https://github.com/neutrinojs/neutrino/tree/master/packages/react',
+        },
+        versions: { '1.0.0': {} },
+      });
+    const registryUrl = resolveRegistryUrl('@neutrinojs/react');
+    const dep = await getDependency(http, registryUrl, '@neutrinojs/react');
+
+    expect(dep.sourceUrl).toBe('https://github.com/neutrinojs/neutrino');
+    expect(dep.sourceDirectory).toBe('packages/react');
+  });
+
   it('handles mixed sourceUrls in releases', async () => {
     setNpmrc('registry=https://test.org\n_authToken=XXX');
 
diff --git a/lib/modules/datasource/npm/get.ts b/lib/modules/datasource/npm/get.ts
index 44d1c7aa93b81c66c6b0b285f3bf7d6f05dd84b7..169b8330cd66cd740f7a9393859d0b6aaf208d49 100644
--- a/lib/modules/datasource/npm/get.ts
+++ b/lib/modules/datasource/npm/get.ts
@@ -87,9 +87,9 @@ export async function getDependency(
       return null;
     }
 
-    const latestVersion = res.versions[res['dist-tags'].latest];
-    res.repository = res.repository || latestVersion.repository;
-    res.homepage = res.homepage || latestVersion.homepage;
+    const latestVersion = res.versions[res['dist-tags']?.latest];
+    res.repository = res.repository || latestVersion?.repository;
+    res.homepage = res.homepage || latestVersion?.homepage;
 
     const { sourceUrl, sourceDirectory } = getPackageSource(res.repository);
 
@@ -105,7 +105,7 @@ export async function getDependency(
       registryUrl,
     };
 
-    if (latestVersion.deprecated) {
+    if (latestVersion?.deprecated) {
       dep.deprecationMessage = `On registry \`${registryUrl}\`, the "latest" version of dependency \`${packageName}\` has the following deprecation notice:\n\n\`${latestVersion.deprecated}\`\n\nMarking the latest version of an npm package as deprecated results in the entire package being considered deprecated, so contact the package author you think this is a mistake.`;
       dep.deprecationSource = id;
     }
diff --git a/lib/modules/datasource/npm/types.ts b/lib/modules/datasource/npm/types.ts
index 10b600a75b0e3924456101f889e2e2e38dc5dd0f..facc963e7ada25130e94d2c96206186a5571af28 100644
--- a/lib/modules/datasource/npm/types.ts
+++ b/lib/modules/datasource/npm/types.ts
@@ -42,7 +42,7 @@ export interface NpmDependency extends ReleaseResult {
   homepage: string;
   sourceUrl: string;
   versions: Record<string, any>;
-  'dist-tags': Record<string, string>;
+  'dist-tags'?: Record<string, string>;
   sourceDirectory?: string;
 }