It seems the bpy.types.NodeSocketVirtual class is responsible for the behavior.
Here is the result of dir(NodeSocketVirtual):
['__class__', '__contains__', '__delattr__', '__delitem__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__init_subclass__', '__le__', '__lt__', '__module__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__sizeof__', '__slots__', '__str__', '__subclasshook__', 'as_pointer', 'bl_rna', 'bl_rna_get_subclass', 'bl_rna_get_subclass_py', 'driver_add', 'driver_remove', 'get', 'id_data', 'id_properties_clear', 'id_properties_ensure', 'id_properties_ui', 'is_property_hidden', 'is_property_overridable_library', 'is_property_readonly', 'is_property_set', 'items', 'keyframe_delete', 'keyframe_insert', 'keys', 'links', 'path_from_id', 'path_resolve', 'pop', 'property_overridable_library_set', 'property_unset', 'type_recast', 'values']
It does not appear to have the poll function I was expecting. Nor does the node itself NodeGroupInput, have the ‘socket_value_update’ function I was expecting (which would usually be used to mark or disconnect illegal links).
Thus I believe this is a regression bug in Blender. I would like a second pair of eyes to look at it, though. I can prepare a minimal example later, perhaps… although node API is very hands-on and requires a lot of Python to produce a minimal example.
EDIT:
The relevant files in Sorcar are https://github.com/aachman98/Sorcar/blob/master/nodes/utilities/ScNodeGroup.py
and
https://github.com/aachman98/Sorcar/blob/master/operators/ScGroupNodes.py
The bug occurs on line 85 of this file, when attempting to connect the GroupInput node to a custom node, but Python does not throw an error until line 94, when previously functional code would attach a link to the newly-created input in the Group Node.