{"record":{"id":"2e5c9c7e3e0deb35","repo":"puppetlabs/puppet","slug":"type-alias-name-cannot-be-resolved-to-a-real","errorCode":null,"errorMessage":"Type alias '#{name}' cannot be resolved to a real type","messagePattern":"Type alias '#(.+?)' cannot be resolved to a real type","errorType":"exception","errorClass":"ArgumentError","httpStatus":null,"severity":"error","filePath":"lib/puppet/pops/types/types.rb","lineNumber":3506,"sourceCode":"    if @resolved_type.nil?\n      # resolved to PTypeReferenceType::DEFAULT during resolve to avoid endless recursion\n      @resolved_type = PTypeReferenceType::DEFAULT\n      @self_recursion = true # assumed while it being found out below\n      begin\n        if @type_expr.is_a?(PTypeReferenceType)\n          @resolved_type = @type_expr.resolve(loader)\n        else\n          @resolved_type = TypeParser.singleton.interpret(@type_expr, loader).normalize\n        end\n\n        # Find out if this type is recursive. A recursive type has performance implications\n        # on several methods and this knowledge is used to avoid that for non-recursive\n        # types.\n        guard = RecursionGuard.new\n        real_type_asserter = AssertOtherTypeAcceptor.new\n        accept(real_type_asserter, guard)\n        unless real_type_asserter.other_type_detected?\n          raise ArgumentError, \"Type alias '#{name}' cannot be resolved to a real type\"\n        end\n\n        @self_recursion = guard.recursive_this?(self)\n        # All aliases involved must re-check status since this alias is now resolved\n        if @self_recursion\n          accept(AssertSelfRecursionStatusAcceptor.new, RecursionGuard.new)\n          when_self_recursion_detected\n        end\n      rescue\n        @resolved_type = nil\n        raise\n      end\n    else\n      # An alias may appoint an Object type that isn't resolved yet. The default type\n      # reference is used to prevent endless recursion and should not be resolved here.\n      @resolved_type.resolve(loader) unless @resolved_type.equal?(PTypeReferenceType::DEFAULT)\n    end\n    self","sourceCodeStart":3488,"sourceCodeEnd":3524,"githubUrl":"https://github.com/puppetlabs/puppet/blob/e227c27540975c25aa22d533a52424a9d2fc886a/lib/puppet/pops/types/types.rb#L3488-L3524","documentation":"When a type alias is resolved, Puppet walks the resolved expression with AssertOtherTypeAcceptor to prove it contains at least one type that is not an alias or variant. An alias that resolves only to aliases or unresolved type references - a direct self-reference like 'type Alias = Alias', or a cycle such as 'type A = B; type B = A' - has no concrete meaning, so resolve raises ArgumentError and resets the alias to unresolved.","triggerScenarios":"type MyType = MyType in a module; two or more aliases referencing each other with no concrete type anywhere in the cycle; renaming a type so an existing alias now points at its own name.","commonSituations":"Copy-paste when adding a new alias beside an existing one and forgetting to change the right-hand side; refactors and renames that introduce cycles; namespaced aliases whose short name resolves back to the alias itself.","solutions":["Ground the cycle in at least one concrete type: type A = B plus type B = Integer.","Check the right-hand side for a self-reference (same name as the alias being defined) and fix the target name.","Use fully qualified names so the reference cannot resolve back to the alias."],"exampleFix":"# before (module manifest)\ntype MyType  = MyAlias\ntype MyAlias = MyType      # cycle: ArgumentError at load\n\n# after\ntype MyType  = MyAlias\ntype MyAlias = Integer     # grounded: resolves fine","handlingStrategy":"try-catch","validationCode":"# when generating aliases programmatically, reject self references first\nfail \"alias #{name} references itself\" if expr.strip == name","typeGuard":null,"tryCatchPattern":"begin\n  parser.parse(type_definition_file)   # module load resolves aliases\nrescue ArgumentError => e\n  STDERR.puts \"bad type alias in #{file}: #{e.message}\"   # points at the cyclic alias\nend","preventionTips":["After copy-pasting an alias definition, always rewrite the right-hand side.","Keep aliases grounded: every alias chain must end in a core type.","Run puppet parser validate in CI so cyclic aliases fail at load time, not at apply time."],"tags":["puppet","type-system","type-alias","circular-reference","puppet-dsl"],"backgroundTag":"circular-type-alias","analyzedSha":"e227c27540975c25aa22d533a52424a9d2fc886a","analyzedAt":"2026-08-21T20:49:46.650Z","schemaVersion":2},"datasetVersion":"2026-08-21T23:17:16.201Z"}