diff --git a/lib/modules/datasource/deno/index.spec.ts b/lib/modules/datasource/deno/index.spec.ts
index 11114db83c81c36eb4e3e379e2176f47a3279eb2..32958a9806aae6c94149dee59420068a8fbf3aa2 100644
--- a/lib/modules/datasource/deno/index.spec.ts
+++ b/lib/modules/datasource/deno/index.spec.ts
@@ -1,4 +1,6 @@
+import { ZodError } from 'zod';
 import * as httpMock from '../../../../test/http-mock';
+import { logger } from '../../../../test/util';
 import { DenoDatasource } from '.';
 
 describe('modules/datasource/deno/index', () => {
@@ -10,7 +12,7 @@ describe('modules/datasource/deno/index', () => {
         .scope(deno.defaultRegistryUrls[0])
         .get('/v2/modules/std')
         .reply(200, {
-          versions: ['0.163.0', '0.162.0'],
+          versions: ['0.163.0', '0.162.0', '0.161.0'],
           tags: [{ value: 'top_5_percent', kind: 'popularity' }],
         })
         .get('/v2/modules/std/0.163.0')
@@ -32,7 +34,9 @@ describe('modules/datasource/deno/index', () => {
             type: 'github',
           },
           uploaded_at: '2022-10-20T12:10:21.592Z',
-        });
+        })
+        .get('/v2/modules/std/0.161.0')
+        .reply(200, { foo: 'bar' });
 
       const result = await deno.getReleases({
         packageName: 'https://deno.land/std',
@@ -50,11 +54,21 @@ describe('modules/datasource/deno/index', () => {
             sourceUrl: 'https://github.com/denoland/deno_std',
             releaseTimestamp: '2022-10-20T12:10:21.592Z',
           },
+          {
+            version: '0.161.0',
+          },
         ],
         tags: {
           popularity: 'top_5_percent',
         },
       });
+
+      expect(logger.logger.warn).toHaveBeenCalledWith(
+        expect.objectContaining({
+          err: expect.any(ZodError),
+        }),
+        `Deno: failed to get version details for 0.161.0`
+      );
     });
 
     it('throws error if module endpoint fails', async () => {
diff --git a/lib/modules/datasource/deno/index.ts b/lib/modules/datasource/deno/index.ts
index 81b42542b57e2d0cbf05362a829897d3d56e36ec..c0b63417fed450c2e7efbf85ee078f567f301fab 100644
--- a/lib/modules/datasource/deno/index.ts
+++ b/lib/modules/datasource/deno/index.ts
@@ -9,12 +9,7 @@ import * as semanticVersioning from '../../versioning/semver';
 import { Datasource } from '../datasource';
 import type { Release } from '../index';
 import type { GetReleasesConfig, ReleaseResult } from '../types';
-import type {
-  DenoAPIModuleResponse,
-  DenoAPIModuleVersionResponse,
-  ReleaseMap,
-} from './types';
-import { createSourceURL, tagsToRecord } from './utils';
+import { DenoAPIModuleResponse, DenoAPIModuleVersionResponse } from './schema';
 
 export class DenoDatasource extends Datasource {
   static readonly id = 'deno';
@@ -45,7 +40,7 @@ export class DenoDatasource extends Datasource {
     const massagedRegistryUrl = registryUrl!;
 
     const extractResult = regEx(
-      '^(https://deno.land/)(?<rawPackageName>[^@\\s]+)'
+      /^(https:\/\/deno.land\/)(?<rawPackageName>[^@\s]+)/
     ).exec(packageName);
     const rawPackageName = extractResult?.groups?.rawPackageName;
     if (is.nullOrUndefined(rawPackageName)) {
@@ -73,17 +68,17 @@ export class DenoDatasource extends Datasource {
     key: (moduleAPIURL) => moduleAPIURL,
   })
   async getReleaseResult(moduleAPIURL: string): Promise<ReleaseResult> {
-    const { versions, tags } = (
-      await this.http.getJson<DenoAPIModuleResponse>(moduleAPIURL)
-    ).body;
-
-    const releasesCache =
-      (await packageCache.get<ReleaseMap>(
+    const releasesCache: Record<string, Release> =
+      (await packageCache.get(
         `datasource-${DenoDatasource.id}-details`,
         moduleAPIURL
       )) ?? {};
     let cacheModified = false;
 
+    const {
+      body: { versions, tags },
+    } = await this.http.getJson(moduleAPIURL, DenoAPIModuleResponse);
+
     // get details for the versions
     const releases = await pMap(
       versions,
@@ -95,8 +90,16 @@ export class DenoDatasource extends Datasource {
         }
 
         // https://apiland.deno.dev/v2/modules/postgres/v0.17.0
-        const release = await this.getReleaseDetails(
-          joinUrlParts(moduleAPIURL, version)
+        const url = joinUrlParts(moduleAPIURL, version);
+        const { body: release } = await this.http.getJson(
+          url,
+          DenoAPIModuleVersionResponse.catch(({ error: err }) => {
+            logger.warn(
+              { err },
+              `Deno: failed to get version details for ${version}`
+            );
+            return { version };
+          })
         );
 
         releasesCache[release.version] = release;
@@ -117,21 +120,6 @@ export class DenoDatasource extends Datasource {
       );
     }
 
-    return {
-      releases,
-      tags: tagsToRecord(tags),
-    };
-  }
-
-  async getReleaseDetails(moduleAPIVersionURL: string): Promise<Release> {
-    const { version, uploaded_at, upload_options } = (
-      await this.http.getJson<DenoAPIModuleVersionResponse>(moduleAPIVersionURL)
-    ).body;
-    return {
-      version,
-      gitRef: upload_options.ref,
-      releaseTimestamp: uploaded_at,
-      sourceUrl: createSourceURL(upload_options),
-    };
+    return { releases, tags };
   }
 }
diff --git a/lib/modules/datasource/deno/schema.ts b/lib/modules/datasource/deno/schema.ts
new file mode 100644
index 0000000000000000000000000000000000000000..412c379776e896c15f87ea5ac00cc1fc478906f3
--- /dev/null
+++ b/lib/modules/datasource/deno/schema.ts
@@ -0,0 +1,44 @@
+import { z } from 'zod';
+import { getSourceUrl as getGithubSourceUrl } from '../../../util/github/url';
+import { looseArray } from '../../../util/schema-utils';
+import type { Release } from '../types';
+
+export const DenoApiTag = z.object({
+  kind: z.string(),
+  value: z.string(),
+});
+
+export const DenoAPIModuleResponse = z.object({
+  tags: looseArray(DenoApiTag).transform((tags) => {
+    const record: Record<string, string> = {};
+    for (const { kind, value } of tags) {
+      record[kind] = value;
+    }
+    return record;
+  }),
+  versions: z.array(z.string()),
+});
+
+export const DenoAPIUploadOptions = z.object({
+  ref: z.string(),
+  type: z.union([z.literal('github'), z.unknown()]),
+  repository: z.string(),
+  subdir: z.string().optional(),
+});
+
+export const DenoAPIModuleVersionResponse = z
+  .object({
+    upload_options: DenoAPIUploadOptions,
+    uploaded_at: z.string(),
+    version: z.string(),
+  })
+  .transform(
+    ({ version, uploaded_at: releaseTimestamp, upload_options }): Release => {
+      let sourceUrl: string | undefined = undefined;
+      const { type, repository, ref: gitRef } = upload_options;
+      if (type === 'github') {
+        sourceUrl = getGithubSourceUrl(repository);
+      }
+      return { version, gitRef, releaseTimestamp, sourceUrl };
+    }
+  );
diff --git a/lib/modules/datasource/deno/types.ts b/lib/modules/datasource/deno/types.ts
deleted file mode 100644
index b130637b8f149885f7cc45922c23ba590457d591..0000000000000000000000000000000000000000
--- a/lib/modules/datasource/deno/types.ts
+++ /dev/null
@@ -1,34 +0,0 @@
-import type { Release } from '../types';
-
-export interface DenoAPIModuleResponse {
-  name: string;
-  latest_version: string;
-  star_count: number;
-  popularity_score: number;
-  tags: DenoAPITags[];
-  versions: string[];
-  description: string;
-}
-
-export interface DenoAPIModuleVersionResponse {
-  upload_options: DenoAPIUploadOptions;
-  analysis_version: string;
-  description: string;
-  uploaded_at: string; // ISO date
-  name: string;
-  version: string;
-}
-
-export interface DenoAPIUploadOptions {
-  ref: string; // commit ref / tag
-  type: 'github' | unknown; // type of hosting. seen: ['github']
-  repository: string; // repo of hosting e.g. denodrivers/postgres
-  subdir?: string;
-}
-
-export interface DenoAPITags {
-  kind: string; // e.g. popularity
-  value: string; // e.g. top_5_percent
-}
-
-export type ReleaseMap = Record<string, Release>;
diff --git a/lib/modules/datasource/deno/utils.ts b/lib/modules/datasource/deno/utils.ts
deleted file mode 100644
index 322928c114b8b8ade3897503684033d897859018..0000000000000000000000000000000000000000
--- a/lib/modules/datasource/deno/utils.ts
+++ /dev/null
@@ -1,22 +0,0 @@
-import { getSourceUrl as getGithubSourceUrl } from '../../../util/github/url';
-import type { DenoAPITags, DenoAPIUploadOptions } from './types';
-
-export function createSourceURL({
-  type,
-  repository,
-}: DenoAPIUploadOptions): string | undefined {
-  switch (type) {
-    case 'github':
-      return getGithubSourceUrl(repository);
-    default:
-      return undefined;
-  }
-}
-
-export function tagsToRecord(tags: DenoAPITags[]): Record<string, string> {
-  const record: Record<string, string> = {};
-  for (const { kind, value } of tags) {
-    record[kind] = value;
-  }
-  return record;
-}