diff --git a/src/Bicep.Core.IntegrationTests/UserDefinedTypeTests.cs b/src/Bicep.Core.IntegrationTests/UserDefinedTypeTests.cs
index 9cae140dc9d..442bcaffe7a 100644
--- a/src/Bicep.Core.IntegrationTests/UserDefinedTypeTests.cs
+++ b/src/Bicep.Core.IntegrationTests/UserDefinedTypeTests.cs
@@ -1823,4 +1823,19 @@ param siteProperties resourceInput<'Microsoft.Web/sites@2022-09-01'>.properties
             """The property "availabilityState" is read-only. Expressions cannot be assigned to read-only properties."""
         );
     }
+
+    [DataTestMethod]
+    [DataRow("type resourceInput = resourceInput<'Microsoft.Compute/virtualMachines'>")] // should be caught at syntax level
+    [DataRow("type resourceInput = resourceInput<'Microsoft.Compute/virtualMachines'>.properties")] // should be caught by type manager
+    public void Parameterized_type_recursion_raises_diagnostic(string template)
+    {
+        var result = CompilationHelper.Compile(
+            new ServiceBuilder().WithFeatureOverrides(new(TestContext, ResourceDerivedTypesEnabled: true)),
+            template);
+
+        result.Should().HaveDiagnostics(new[]
+        {
+            ("BCP298", DiagnosticLevel.Error, "This type definition includes itself as required component, which creates a constraint that cannot be fulfilled."),
+        });
+    }
 }
diff --git a/src/Bicep.Core/TypeSystem/CyclicCheckVisitor.cs b/src/Bicep.Core/TypeSystem/CyclicCheckVisitor.cs
index 6fc9cddfca5..fc3986b12ab 100644
--- a/src/Bicep.Core/TypeSystem/CyclicCheckVisitor.cs
+++ b/src/Bicep.Core/TypeSystem/CyclicCheckVisitor.cs
@@ -167,6 +167,18 @@ public override void VisitFunctionCallSyntax(FunctionCallSyntax syntax)
             base.VisitFunctionCallSyntax(syntax);
         }
 
+        public override void VisitParameterizedTypeInstantiationSyntax(ParameterizedTypeInstantiationSyntax syntax)
+        {
+            if (!currentDeclarations.TryPeek(out var currentDeclaration))
+            {
+                // we're not inside a declaration, so there should be no risk of a cycle
+                return;
+            }
+
+            declarationAccessDict[currentDeclaration].Add(syntax);
+            base.VisitParameterizedTypeInstantiationSyntax(syntax);
+        }
+
         public override void VisitArrayTypeMemberSyntax(ArrayTypeMemberSyntax syntax)
             => WithSelfReferencePermitted(() => base.VisitArrayTypeMemberSyntax(syntax), selfReferencePermitted: true);
 
diff --git a/src/Bicep.Core/TypeSystem/CyclicTypeCheckVisitor.cs b/src/Bicep.Core/TypeSystem/CyclicTypeCheckVisitor.cs
index 8c1c02e51b1..422eb30d8bd 100644
--- a/src/Bicep.Core/TypeSystem/CyclicTypeCheckVisitor.cs
+++ b/src/Bicep.Core/TypeSystem/CyclicTypeCheckVisitor.cs
@@ -72,6 +72,18 @@ public override void VisitTypeVariableAccessSyntax(TypeVariableAccessSyntax synt
         base.VisitTypeVariableAccessSyntax(syntax);
     }
 
+    public override void VisitParameterizedTypeInstantiationSyntax(ParameterizedTypeInstantiationSyntax syntax)
+    {
+        // If this reference is not nested within a type container, it would have been detected based on syntax alone in CyclicCheckVisitor.
+        // To avoid doubling up on diagnostics, skip recording cycles on top-level accesses
+        if (enteredTypeContainer)
+        {
+            declarationAccesses.Add(syntax);
+        }
+
+        base.VisitParameterizedTypeInstantiationSyntax(syntax);
+    }
+
     public override void VisitArrayTypeSyntax(ArrayTypeSyntax syntax)
         => WithEnteredTypeContainerState(() => base.VisitArrayTypeSyntax(syntax), enteredTypeContainer: true);
 
diff --git a/src/Bicep.Core/TypeSystem/DeclaredTypeManager.cs b/src/Bicep.Core/TypeSystem/DeclaredTypeManager.cs
index 1fcef5662aa..1ac7501b94f 100644
--- a/src/Bicep.Core/TypeSystem/DeclaredTypeManager.cs
+++ b/src/Bicep.Core/TypeSystem/DeclaredTypeManager.cs
@@ -259,9 +259,6 @@ private DeclaredTypeAssignment GetTypeType(TypeDeclarationSyntax syntax)
 
         private TypeSymbol GetUserDefinedTypeType(TypeAliasSymbol symbol)
         {
-            // Even if the declared type is invalid because of a illegal cycle, we still want to visit (and cache the type of) nested elements.
-            var declaredType = GetTypeFromTypeSyntax(symbol.DeclaringType.Value);
-
             if (binder.TryGetCycle(symbol) is { } cycle)
             {
                 var builder = DiagnosticBuilder.ForPosition(symbol.DeclaringType.Name);
@@ -272,7 +269,9 @@ private TypeSymbol GetUserDefinedTypeType(TypeAliasSymbol symbol)
                 return ErrorType.Create(diagnostic);
             }
 
-            return ApplyTypeModifyingDecorators(DisallowNamespaceTypes(declaredType.Type, symbol.DeclaringType.Value), symbol.DeclaringType);
+            return ApplyTypeModifyingDecorators(
+                DisallowNamespaceTypes(GetTypeFromTypeSyntax(symbol.DeclaringType.Value).Type, symbol.DeclaringType.Value),
+                symbol.DeclaringType);
         }
 
         private static ITypeReference DisallowNamespaceTypes(ITypeReference typeReference, SyntaxBase syntax) => typeReference switch