@@ -307,6 +307,10 @@ private void TryApplyPayloadConvention(
307307 _typeRegistry . TryRegister (
308308 _context . TypeInspector . GetOutputTypeRef ( errorDef . RuntimeType ) ,
309309 errorTypeRef ) ;
310+ if ( ! typeof ( Exception ) . IsAssignableFrom ( errorDef . RuntimeType ) )
311+ {
312+ EnsureMemberTypesRegistered ( errorDef . RuntimeType ) ;
313+ }
310314 ( ( ObjectType ) obj . Type ) . Configuration ! . Interfaces . Add ( errorInterfaceTypeRef ) ;
311315 }
312316
@@ -623,6 +627,19 @@ private static Options CreateErrorOptions(
623627 _typeInitializer . CompleteTypeName ( registeredType ) ;
624628 _typeInitializer . CompileResolvers ( registeredType ) ;
625629
630+ // Late-registered types bypass the normal discovery pipeline; add a direct runtime
631+ // binding so output field references (e.g. Int32! on error objects) can normalize.
632+ _typeRegistry . TryRegister (
633+ _context . TypeInspector . GetOutputTypeRef ( type ) ,
634+ registeredType . TypeReference ) ;
635+
636+ if ( registeredType . RuntimeType != typeof ( object ) )
637+ {
638+ _typeRegistry . TryRegister (
639+ _context . TypeInspector . GetOutputTypeRef ( registeredType . RuntimeType ) ,
640+ registeredType . TypeReference ) ;
641+ }
642+
626643 if ( registeredType . Type is ObjectType errorObject
627644 && errorObject . RuntimeType != typeof ( object ) )
628645 {
@@ -665,6 +682,81 @@ private static Options CreateErrorOptions(
665682 return registeredType ;
666683 }
667684
685+ private void EnsureMemberTypesRegistered ( Type runtimeType )
686+ {
687+ HashSet < Type > processed = [ ] ;
688+ EnsureMemberTypesRegistered ( runtimeType , processed ) ;
689+ }
690+
691+ private void EnsureMemberTypesRegistered (
692+ Type runtimeType ,
693+ HashSet < Type > processed )
694+ {
695+ if ( ! processed . Add ( runtimeType ) )
696+ {
697+ return ;
698+ }
699+
700+ foreach ( var member in _context . TypeInspector . GetMembers ( runtimeType ) )
701+ {
702+ var memberTypeReference = _context . TypeInspector . GetReturnTypeRef ( member , TypeContext . Output ) ;
703+ EnsureTypeReferenceRegistered ( memberTypeReference , processed ) ;
704+ }
705+ }
706+
707+ private void EnsureTypeReferenceRegistered (
708+ TypeReference typeReference ,
709+ HashSet < Type > processed )
710+ {
711+ if ( typeReference is not ExtendedTypeReference runtimeTypeReference )
712+ {
713+ return ;
714+ }
715+
716+ if ( _typeRegistry . TryGetTypeRef ( runtimeTypeReference , out var existingTypeReference )
717+ && _typeRegistry . IsRegistered ( existingTypeReference ) )
718+ {
719+ return ;
720+ }
721+
722+ if ( ! _context . TryInferSchemaType ( typeReference , out var schemaTypeReferences ) )
723+ {
724+ return ;
725+ }
726+
727+ foreach ( var schemaTypeReference in schemaTypeReferences )
728+ {
729+ _typeRegistry . TryRegister (
730+ runtimeTypeReference . WithContext ( schemaTypeReference . Context ) ,
731+ schemaTypeReference ) ;
732+
733+ var schemaClrType = schemaTypeReference switch
734+ {
735+ SchemaTypeReference { Type : TypeSystemObject schemaType } => schemaType . GetType ( ) ,
736+ ExtendedTypeReference { Type : { IsSchemaType : true } schemaType } => schemaType . Type ,
737+ _ => null
738+ } ;
739+
740+ if ( schemaClrType is null )
741+ {
742+ continue ;
743+ }
744+
745+ var dependencyType = TryRegisterType ( schemaClrType ) ;
746+ if ( dependencyType is not { RuntimeType : { } dependencyRuntimeType } )
747+ {
748+ continue ;
749+ }
750+
751+ if ( dependencyRuntimeType != typeof ( object )
752+ && dependencyRuntimeType != typeof ( string )
753+ && ! dependencyRuntimeType . IsPrimitive )
754+ {
755+ EnsureMemberTypesRegistered ( dependencyRuntimeType , processed ) ;
756+ }
757+ }
758+ }
759+
668760 private void RegisterType ( TypeSystemObject type )
669761 {
670762 var registeredType = _typeInitializer . InitializeType ( type ) ;
0 commit comments