diff --git a/lib/modules/versioning/composer/index.spec.ts b/lib/modules/versioning/composer/index.spec.ts
index f11774f78c33087e2ba272088ea5098f75bec3f9..e1bcbd602e90daf4dbf0e0f4c04b04ff4d127fb3 100644
--- a/lib/modules/versioning/composer/index.spec.ts
+++ b/lib/modules/versioning/composer/index.spec.ts
@@ -69,6 +69,8 @@ describe('modules/versioning/composer/index', () => {
     ${'~1.0 | ~2.0'}  | ${true}
     ${'~1.0||~2.0'}   | ${true}
     ${'~1.0 || ~2.0'} | ${true}
+    ${'<8.0-DEV'}     | ${true}
+    ${'<8-DEV'}       | ${true}
   `('isValid("$version") === $expected', ({ version, expected }) => {
     const res = !!semver.isValid(version);
     expect(res).toBe(expected);
@@ -134,6 +136,8 @@ describe('modules/versioning/composer/index', () => {
     ${'^1.0.0'}           | ${'^0.9.0'}           | ${false}
     ${'^1.1.0 || ^2.0.0'} | ${'^1.0.0 || ^2.0.0'} | ${true}
     ${'^1.0.0 || ^2.0.0'} | ${'^1.1.0 || ^2.0.0'} | ${false}
+    ${'^7.0.0'}           | ${'<8.0-DEV'}         | ${true}
+    ${'^7.0.0'}           | ${'less than 8'}      | ${false}
   `('subset("$a", "$b") === $expected', ({ a, b, expected }) => {
     expect(semver.subset!(a, b)).toBe(expected);
   });
diff --git a/lib/modules/versioning/composer/index.ts b/lib/modules/versioning/composer/index.ts
index 7fc94cd290cc9cd2a40d7203573e6b2ae31dccc9..9a6a2ef905fada4bb7842a5cdbf8ce107a0f6207 100644
--- a/lib/modules/versioning/composer/index.ts
+++ b/lib/modules/versioning/composer/index.ts
@@ -91,6 +91,11 @@ function composer2npm(input: string): string {
         '>=$1 <1'
       );
 
+      // add extra digits to <8-DEV and <8.0-DEV
+      output = output
+        .replace(regEx(/^(<\d+(\.\d+)?)$/g), '$1.0')
+        .replace(regEx(/^(<\d+(\.\d+)?)$/g), '$1.0');
+
       return output + stability;
     })
     .map((part) => part.replace(/([a-z])([0-9])/gi, '$1.$2'))
@@ -171,7 +176,12 @@ function minSatisfyingVersion(
 }
 
 function subset(subRange: string, superRange: string): boolean | undefined {
-  return npm.subset!(composer2npm(subRange), composer2npm(superRange));
+  try {
+    return npm.subset!(composer2npm(subRange), composer2npm(superRange));
+  } catch (err) {
+    logger.trace({ err }, 'composer.subset error');
+    return false;
+  }
 }
 
 function getNewValue({