diff --git a/lib/types/skip-reason.ts b/lib/types/skip-reason.ts
index 1f11d3b848c224b3dce8a88e4b4d64f89c39d1a5..41baf0f14f5462f0318d441c5a1f8cc68d849170 100644
--- a/lib/types/skip-reason.ts
+++ b/lib/types/skip-reason.ts
@@ -8,6 +8,7 @@ export enum SkipReason {
   GitDependency = 'git-dependency',
   GitPlugin = 'git-plugin',
   Ignored = 'ignored',
+  InternalError = 'internal-error',
   InternalPackage = 'internal-package',
   InvalidConfig = 'invalid-config',
   InvalidDependencySpecification = 'invalid-dependency-specification',
diff --git a/lib/workers/repository/process/lookup/index.ts b/lib/workers/repository/process/lookup/index.ts
index 9f82d0191bd69aa5cba3b0704e7f1446c629e3cc..ad0d46dd9c9619d58dd2f95d584f34abff3b7963 100644
--- a/lib/workers/repository/process/lookup/index.ts
+++ b/lib/workers/repository/process/lookup/index.ts
@@ -1,5 +1,6 @@
 import { mergeChildConfig } from '../../../../config';
 import type { ValidationMessage } from '../../../../config/types';
+import { CONFIG_VALIDATION } from '../../../../constants/error-messages';
 import {
   Release,
   getDatasourceList,
@@ -12,6 +13,7 @@ import {
 import { logger } from '../../../../logger';
 import { getRangeStrategy } from '../../../../manager';
 import { SkipReason } from '../../../../types';
+import { ExternalHostError } from '../../../../types/errors/external-host-error';
 import { clone } from '../../../../util/clone';
 import { applyPackageRules } from '../../../../util/package-rules';
 import { regEx } from '../../../../util/regex';
@@ -42,296 +44,326 @@ export async function lookupUpdates(
     isVulnerabilityAlert,
     updatePinnedDependencies,
   } = config;
-  logger.trace({ dependency: depName, currentValue }, 'lookupUpdates');
-  // Use the datasource's default versioning if none is configured
-  config.versioning ??= getDefaultVersioning(datasource);
-  const versioning = allVersioning.get(config.versioning);
   const res: UpdateResult = {
     updates: [],
     warnings: [],
-    versioning: config.versioning,
   } as any;
-  // istanbul ignore if
-  if (
-    !isGetPkgReleasesConfig(config) ||
-    !getDatasourceList().includes(datasource)
-  ) {
-    res.skipReason = SkipReason.InvalidConfig;
-    return res;
-  }
-  const isValid = currentValue && versioning.isValid(currentValue);
-  if (isValid) {
-    if (!updatePinnedDependencies && versioning.isSingleVersion(currentValue)) {
-      res.skipReason = SkipReason.IsPinned;
-      return res;
-    }
-
-    const dependency = clone(await getPkgReleases(config));
-    if (!dependency) {
-      // If dependency lookup fails then warn and return
-      const warning: ValidationMessage = {
-        topic: depName,
-        message: `Failed to look up dependency ${depName}`,
-      };
-      logger.debug({ dependency: depName, packageFile }, warning.message);
-      // TODO: return warnings in own field
-      res.warnings.push(warning);
+  try {
+    logger.trace({ dependency: depName, currentValue }, 'lookupUpdates');
+    // Use the datasource's default versioning if none is configured
+    config.versioning ??= getDefaultVersioning(datasource);
+    const versioning = allVersioning.get(config.versioning);
+    res.versioning = config.versioning;
+    // istanbul ignore if
+    if (
+      !isGetPkgReleasesConfig(config) ||
+      !getDatasourceList().includes(datasource)
+    ) {
+      res.skipReason = SkipReason.InvalidConfig;
       return res;
     }
-    if (dependency.deprecationMessage) {
-      logger.debug({ dependency: depName }, 'Found deprecationMessage');
-      res.deprecationMessage = dependency.deprecationMessage;
-    }
-    res.sourceUrl = dependency?.sourceUrl;
-    if (dependency.sourceDirectory) {
-      res.sourceDirectory = dependency.sourceDirectory;
-    }
-    res.homepage = dependency.homepage;
-    res.changelogUrl = dependency.changelogUrl;
-    res.dependencyUrl = dependency?.dependencyUrl;
-
-    const latestVersion = dependency.tags?.latest;
-    // Filter out any results from datasource that don't comply with our versioning
-    let allVersions = dependency.releases.filter((release) =>
-      versioning.isVersion(release.version)
-    );
-    // istanbul ignore if
-    if (allVersions.length === 0) {
-      const message = `Found no results from datasource that look like a version`;
-      logger.debug({ dependency: depName, result: dependency }, message);
-      if (!currentDigest) {
+    const isValid = currentValue && versioning.isValid(currentValue);
+    if (isValid) {
+      if (
+        !updatePinnedDependencies &&
+        versioning.isSingleVersion(currentValue)
+      ) {
+        res.skipReason = SkipReason.IsPinned;
         return res;
       }
-    }
-    // Reapply package rules in case we missed something from sourceUrl
-    config = applyPackageRules({ ...config, sourceUrl: res.sourceUrl });
-    if (followTag) {
-      const taggedVersion = dependency.tags[followTag];
-      if (!taggedVersion) {
-        res.warnings.push({
+
+      const dependency = clone(await getPkgReleases(config));
+      if (!dependency) {
+        // If dependency lookup fails then warn and return
+        const warning: ValidationMessage = {
           topic: depName,
-          message: `Can't find version with tag ${followTag} for ${depName}`,
-        });
+          message: `Failed to look up dependency ${depName}`,
+        };
+        logger.debug({ dependency: depName, packageFile }, warning.message);
+        // TODO: return warnings in own field
+        res.warnings.push(warning);
         return res;
       }
-      allVersions = allVersions.filter(
-        (v) =>
-          v.version === taggedVersion ||
-          (v.version === currentValue &&
-            versioning.isGreaterThan(taggedVersion, currentValue))
+      if (dependency.deprecationMessage) {
+        logger.debug({ dependency: depName }, 'Found deprecationMessage');
+        res.deprecationMessage = dependency.deprecationMessage;
+      }
+      res.sourceUrl = dependency?.sourceUrl;
+      if (dependency.sourceDirectory) {
+        res.sourceDirectory = dependency.sourceDirectory;
+      }
+      res.homepage = dependency.homepage;
+      res.changelogUrl = dependency.changelogUrl;
+      res.dependencyUrl = dependency?.dependencyUrl;
+
+      const latestVersion = dependency.tags?.latest;
+      // Filter out any results from datasource that don't comply with our versioning
+      let allVersions = dependency.releases.filter((release) =>
+        versioning.isVersion(release.version)
       );
-    }
-    // Check that existing constraint can be satisfied
-    const allSatisfyingVersions = allVersions.filter((v) =>
-      versioning.matches(v.version, currentValue)
-    );
-    if (rollbackPrs && !allSatisfyingVersions.length) {
-      const rollback = getRollbackUpdate(config, allVersions, versioning);
       // istanbul ignore if
-      if (!rollback) {
-        res.warnings.push({
-          topic: depName,
-          message: `Can't find version matching ${currentValue} for ${depName}`,
-        });
-        return res;
+      if (allVersions.length === 0) {
+        const message = `Found no results from datasource that look like a version`;
+        logger.debug({ dependency: depName, result: dependency }, message);
+        if (!currentDigest) {
+          return res;
+        }
       }
-      res.updates.push(rollback);
-    }
-    let rangeStrategy = getRangeStrategy(config);
-    // istanbul ignore next
-    if (
-      isVulnerabilityAlert &&
-      rangeStrategy === 'update-lockfile' &&
-      !lockedVersion
-    ) {
-      rangeStrategy = 'bump';
-    }
-    const nonDeprecatedVersions = dependency.releases
-      .filter((release) => !release.isDeprecated)
-      .map((release) => release.version);
-    const currentVersion =
-      getCurrentVersion(
-        config,
-        versioning,
-        rangeStrategy,
-        latestVersion,
-        nonDeprecatedVersions
-      ) ||
-      getCurrentVersion(
-        config,
-        versioning,
-        rangeStrategy,
-        latestVersion,
-        allVersions.map((v) => v.version)
-      );
-    // istanbul ignore if
-    if (!currentVersion && lockedVersion) {
-      return res;
-    }
-    res.currentVersion = currentVersion;
-    if (
-      currentVersion &&
-      rangeStrategy === 'pin' &&
-      !versioning.isSingleVersion(currentValue)
-    ) {
-      res.updates.push({
-        updateType: 'pin',
-        isPin: true,
-        newValue: versioning.getNewValue({
-          currentValue,
-          rangeStrategy,
-          currentVersion,
-          newVersion: currentVersion,
-        }),
-        newMajor: versioning.getMajor(currentVersion),
-      });
-    }
-    let filterStart = currentVersion;
-    if (lockedVersion && rangeStrategy === 'update-lockfile') {
-      // Look for versions greater than the current locked version that still satisfy the package.json range
-      filterStart = lockedVersion;
-    }
-    // Filter latest, unstable, etc
-    let filteredReleases = filterVersions(
-      config,
-      filterStart,
-      latestVersion,
-      allVersions,
-      versioning
-    ).filter((v) =>
-      // Leave only compatible versions
-      versioning.isCompatible(v.version, currentValue)
-    );
-    if (isVulnerabilityAlert) {
-      filteredReleases = filteredReleases.slice(0, 1);
-    }
-    const buckets: Record<string, [Release]> = {};
-    for (const release of filteredReleases) {
-      const bucket = getBucket(
-        config,
-        currentVersion,
-        release.version,
-        versioning
-      );
-      if (buckets[bucket]) {
-        buckets[bucket].push(release);
-      } else {
-        buckets[bucket] = [release];
+      // Reapply package rules in case we missed something from sourceUrl
+      config = applyPackageRules({ ...config, sourceUrl: res.sourceUrl });
+      if (followTag) {
+        const taggedVersion = dependency.tags[followTag];
+        if (!taggedVersion) {
+          res.warnings.push({
+            topic: depName,
+            message: `Can't find version with tag ${followTag} for ${depName}`,
+          });
+          return res;
+        }
+        allVersions = allVersions.filter(
+          (v) =>
+            v.version === taggedVersion ||
+            (v.version === currentValue &&
+              versioning.isGreaterThan(taggedVersion, currentValue))
+        );
       }
-    }
-    const depResultConfig = mergeChildConfig(config, res);
-    for (const [bucket, releases] of Object.entries(buckets)) {
-      const sortedReleases = releases.sort((r1, r2) =>
-        versioning.sortVersions(r1.version, r2.version)
+      // Check that existing constraint can be satisfied
+      const allSatisfyingVersions = allVersions.filter((v) =>
+        versioning.matches(v.version, currentValue)
       );
-      const { release, pendingChecks, pendingReleases } =
-        await filterInternalChecks(
-          depResultConfig,
+      if (rollbackPrs && !allSatisfyingVersions.length) {
+        const rollback = getRollbackUpdate(config, allVersions, versioning);
+        // istanbul ignore if
+        if (!rollback) {
+          res.warnings.push({
+            topic: depName,
+            message: `Can't find version matching ${currentValue} for ${depName}`,
+          });
+          return res;
+        }
+        res.updates.push(rollback);
+      }
+      let rangeStrategy = getRangeStrategy(config);
+      // istanbul ignore next
+      if (
+        isVulnerabilityAlert &&
+        rangeStrategy === 'update-lockfile' &&
+        !lockedVersion
+      ) {
+        rangeStrategy = 'bump';
+      }
+      const nonDeprecatedVersions = dependency.releases
+        .filter((release) => !release.isDeprecated)
+        .map((release) => release.version);
+      const currentVersion =
+        getCurrentVersion(
+          config,
           versioning,
-          bucket,
-          sortedReleases
+          rangeStrategy,
+          latestVersion,
+          nonDeprecatedVersions
+        ) ||
+        getCurrentVersion(
+          config,
+          versioning,
+          rangeStrategy,
+          latestVersion,
+          allVersions.map((v) => v.version)
         );
-      // istanbul ignore next
-      if (!release) {
+      // istanbul ignore if
+      if (!currentVersion && lockedVersion) {
         return res;
       }
-      const newVersion = release.version;
-      const update = generateUpdate(
+      res.currentVersion = currentVersion;
+      if (
+        currentVersion &&
+        rangeStrategy === 'pin' &&
+        !versioning.isSingleVersion(currentValue)
+      ) {
+        res.updates.push({
+          updateType: 'pin',
+          isPin: true,
+          newValue: versioning.getNewValue({
+            currentValue,
+            rangeStrategy,
+            currentVersion,
+            newVersion: currentVersion,
+          }),
+          newMajor: versioning.getMajor(currentVersion),
+        });
+      }
+      let filterStart = currentVersion;
+      if (lockedVersion && rangeStrategy === 'update-lockfile') {
+        // Look for versions greater than the current locked version that still satisfy the package.json range
+        filterStart = lockedVersion;
+      }
+      // Filter latest, unstable, etc
+      let filteredReleases = filterVersions(
         config,
-        versioning,
-        rangeStrategy,
-        lockedVersion || currentVersion,
-        bucket,
-        release
+        filterStart,
+        latestVersion,
+        allVersions,
+        versioning
+      ).filter((v) =>
+        // Leave only compatible versions
+        versioning.isCompatible(v.version, currentValue)
       );
-      if (pendingChecks) {
-        update.pendingChecks = pendingChecks;
-      }
-      if (pendingReleases.length) {
-        update.pendingVersions = pendingReleases.map((r) => r.version);
+      if (isVulnerabilityAlert) {
+        filteredReleases = filteredReleases.slice(0, 1);
       }
-      if (!update.newValue || update.newValue === currentValue) {
-        if (!lockedVersion) {
-          continue; // eslint-disable-line no-continue
+      const buckets: Record<string, [Release]> = {};
+      for (const release of filteredReleases) {
+        const bucket = getBucket(
+          config,
+          currentVersion,
+          release.version,
+          versioning
+        );
+        if (buckets[bucket]) {
+          buckets[bucket].push(release);
+        } else {
+          buckets[bucket] = [release];
         }
-        // istanbul ignore if
-        if (rangeStrategy === 'bump') {
-          logger.trace(
-            { depName, currentValue, lockedVersion, newVersion },
-            'Skipping bump because newValue is the same'
+      }
+      const depResultConfig = mergeChildConfig(config, res);
+      for (const [bucket, releases] of Object.entries(buckets)) {
+        const sortedReleases = releases.sort((r1, r2) =>
+          versioning.sortVersions(r1.version, r2.version)
+        );
+        const { release, pendingChecks, pendingReleases } =
+          await filterInternalChecks(
+            depResultConfig,
+            versioning,
+            bucket,
+            sortedReleases
           );
-          continue; // eslint-disable-line no-continue
+        // istanbul ignore next
+        if (!release) {
+          return res;
         }
-        res.isSingleVersion = true;
-      }
-      res.isSingleVersion =
-        res.isSingleVersion || !!versioning.isSingleVersion(update.newValue);
+        const newVersion = release.version;
+        const update = generateUpdate(
+          config,
+          versioning,
+          rangeStrategy,
+          lockedVersion || currentVersion,
+          bucket,
+          release
+        );
+        if (pendingChecks) {
+          update.pendingChecks = pendingChecks;
+        }
+        if (pendingReleases.length) {
+          update.pendingVersions = pendingReleases.map((r) => r.version);
+        }
+        if (!update.newValue || update.newValue === currentValue) {
+          if (!lockedVersion) {
+            continue; // eslint-disable-line no-continue
+          }
+          // istanbul ignore if
+          if (rangeStrategy === 'bump') {
+            logger.trace(
+              { depName, currentValue, lockedVersion, newVersion },
+              'Skipping bump because newValue is the same'
+            );
+            continue; // eslint-disable-line no-continue
+          }
+          res.isSingleVersion = true;
+        }
+        res.isSingleVersion =
+          res.isSingleVersion || !!versioning.isSingleVersion(update.newValue);
 
-      res.updates.push(update);
-    }
-  } else if (currentValue) {
-    logger.debug(`Dependency ${depName} has unsupported value ${currentValue}`);
-    if (!pinDigests && !currentDigest) {
-      res.skipReason = SkipReason.InvalidValue;
+        res.updates.push(update);
+      }
+    } else if (currentValue) {
+      logger.debug(
+        `Dependency ${depName} has unsupported value ${currentValue}`
+      );
+      if (!pinDigests && !currentDigest) {
+        res.skipReason = SkipReason.InvalidValue;
+      } else {
+        delete res.skipReason;
+      }
     } else {
-      delete res.skipReason;
+      res.skipReason = SkipReason.InvalidValue;
     }
-  } else {
-    res.skipReason = SkipReason.InvalidValue;
-  }
 
-  // Record if the dep is fixed to a version
-  if (lockedVersion) {
-    res.currentVersion = lockedVersion;
-    res.fixedVersion = lockedVersion;
-  } else if (currentValue && versioning.isSingleVersion(currentValue)) {
-    res.fixedVersion = currentValue.replace(regEx(/^=+/), '');
-  }
-  // Add digests if necessary
-  if (supportsDigests(config)) {
-    if (currentDigest) {
-      if (!digestOneAndOnly || !res.updates.length) {
-        // digest update
-        res.updates.push({
-          updateType: 'digest',
-          newValue: currentValue,
-        });
+    // Record if the dep is fixed to a version
+    if (lockedVersion) {
+      res.currentVersion = lockedVersion;
+      res.fixedVersion = lockedVersion;
+    } else if (currentValue && versioning.isSingleVersion(currentValue)) {
+      res.fixedVersion = currentValue.replace(regEx(/^=+/), '');
+    }
+    // Add digests if necessary
+    if (supportsDigests(config)) {
+      if (currentDigest) {
+        if (!digestOneAndOnly || !res.updates.length) {
+          // digest update
+          res.updates.push({
+            updateType: 'digest',
+            newValue: currentValue,
+          });
+        }
+      } else if (pinDigests) {
+        // Create a pin only if one doesn't already exists
+        if (!res.updates.some((update) => update.updateType === 'pin')) {
+          // pin digest
+          res.updates.push({
+            updateType: 'pin',
+            newValue: currentValue,
+          });
+        }
       }
-    } else if (pinDigests) {
-      // Create a pin only if one doesn't already exists
-      if (!res.updates.some((update) => update.updateType === 'pin')) {
-        // pin digest
-        res.updates.push({
-          updateType: 'pin',
-          newValue: currentValue,
-        });
+      if (versioning.valueToVersion) {
+        res.currentVersion = versioning.valueToVersion(res.currentVersion);
+        for (const update of res.updates || []) {
+          update.newVersion = versioning.valueToVersion(update.newVersion);
+        }
       }
-    }
-    if (versioning.valueToVersion) {
-      res.currentVersion = versioning.valueToVersion(res.currentVersion);
-      for (const update of res.updates || []) {
-        update.newVersion = versioning.valueToVersion(update.newVersion);
+      // update digest for all
+      for (const update of res.updates) {
+        if (pinDigests || currentDigest) {
+          update.newDigest =
+            update.newDigest || (await getDigest(config, update.newValue));
+        }
       }
     }
-    // update digest for all
-    for (const update of res.updates) {
-      if (pinDigests || currentDigest) {
-        update.newDigest =
-          update.newDigest || (await getDigest(config, update.newValue));
-      }
+    if (res.updates.length) {
+      delete res.skipReason;
     }
-  }
-  if (res.updates.length) {
-    delete res.skipReason;
-  }
-  // Strip out any non-changed ones
-  res.updates = res.updates
-    .filter((update) => update.newDigest !== null)
-    .filter(
-      (update) =>
-        update.newValue !== currentValue ||
-        update.isLockfileUpdate ||
-        (update.newDigest && !update.newDigest.startsWith(currentDigest))
+    // Strip out any non-changed ones
+    res.updates = res.updates
+      .filter((update) => update.newDigest !== null)
+      .filter(
+        (update) =>
+          update.newValue !== currentValue ||
+          update.isLockfileUpdate ||
+          (update.newDigest && !update.newDigest.startsWith(currentDigest))
+      );
+  } catch (err) /* istanbul ignore next */ {
+    if (err instanceof ExternalHostError || err.message === CONFIG_VALIDATION) {
+      throw err;
+    }
+    logger.error(
+      {
+        currentDigest,
+        currentValue,
+        datasource,
+        depName,
+        digestOneAndOnly,
+        followTag,
+        lockedVersion,
+        packageFile,
+        pinDigests,
+        rollbackPrs,
+        isVulnerabilityAlert,
+        updatePinnedDependencies,
+        err,
+      },
+      'lookupUpdates error'
     );
+    res.skipReason = SkipReason.InternalError;
+  }
   return res;
 }
diff --git a/lib/workers/repository/process/lookup/types.ts b/lib/workers/repository/process/lookup/types.ts
index 2c44ff188e060b913022930a7f7870f551efc6d3..be3200ffd2c1be10e3e8e54e63e2edaf0c5d0519 100644
--- a/lib/workers/repository/process/lookup/types.ts
+++ b/lib/workers/repository/process/lookup/types.ts
@@ -57,6 +57,5 @@ export interface UpdateResult {
   fixedVersion?: string;
   updates: LookupUpdate[];
   warnings: ValidationMessage[];
-
-  versioning: string;
+  versioning?: string;
 }