When a StructureDefinition differential defines slices on the extension of a primitive-type field (e.g., Observation.status.extension:mySlice), FHIRModelFactory.build() raises an AssemblerError wrapping a TypeError:
TypeError: TypeAliasType.__init__() got an unexpected keyword argument '__pydantic_reset_parent_namespace__'
This is because BackboneFieldBuilder incorrectly claims ownership of the primitive element (e.g., Observation.status) once its extension slice children appear in the resolved index — then attempts to use the primitive's TypeAliasType (e.g., ObservationStatus) as a Pydantic __base__, which Pydantic rejects.
Steps to Reproduce
from fhircraft.fhir.resources import FHIRModelFactory
from fhircraft.fhir.resources.generator import CodeGenerator
factory = FHIRModelFactory(fhir_release="R5")
structure_definition_1 = {
"resourceType": "StructureDefinition",
"id": "example-profile-1",
"url": "http://hl7.org/fhir/StructureDefinition/example-profile-1",
"version": "5.0.0",
"name": "ExampleProfile1",
"title": "Example Profile 1",
"status": "draft",
"fhirVersion": "5.0.0",
"kind": "resource",
"abstract": False,
"type": "Observation",
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Observation",
"derivation": "constraint",
"differential": {
"element": [
{"id": "Observation.status", "path": "Observation.status"},
{"id": "Observation.status.extension", "path": "Observation.status.extension"},
{
"id": "Observation.status.extension:mySlice",
"path": "Observation.status.extension",
"sliceName": "mySlice",
"type": [{
"code": "Extension",
"profile": ["http://example.org/fhir/StructureDefinition/my-extension"]
}],
}
]
},
}
extension_structure_definition_1 = {
"resourceType": "StructureDefinition",
"id": "my-extension",
"url": "http://example.org/fhir/StructureDefinition/my-extension",
"version": "0.1.0",
"name": "MyExtension",
"status": "active",
"fhirVersion": "5.0.0",
"kind": "complex-type",
"abstract": False,
"type": "Extension",
"baseDefinition": "http://hl7.org/fhir/StructureDefinition/Extension",
"derivation": "constraint",
"differential": {
"element": [
{"id": "Extension.url", "path": "Extension.url",
"fixedUri": "http://example.org/fhir/StructureDefinition/my-extension"},
{"id": "Extension.value[x]", "path": "Extension.value[x]",
"type": [{"code": "string"}], "min": 1, "max": "1"}
]
},
}
factory.definition_registry.from_dict(structure_definition_1)
factory.definition_registry.from_dict(extension_structure_definition_1)
# Raises AssemblerError
model = factory.build(structure_definition=structure_definition_1, mode="differential")
Full Traceback
File ~/dev/fhircraft/fhircraft/fhir/resources/factory/assembler.py:113, in ModelAssembler.assemble
build = builder.build(child_node, self.index)
File ~/dev/fhircraft/fhircraft/fhir/resources/factory/builders/backbone.py:94, in BackboneFieldBuilder.build
backbone_model = assembler.assemble(backbone_name, base=(backbone_base,))
File ~/dev/fhircraft/fhircraft/fhir/resources/factory/assembler.py:167, in ModelAssembler.assemble
model = create_model(name, **fields, __base__=base_classes, ...)
File .../pydantic/main.py:1809, in create_model
return meta(model_name, resolved_bases, namespace, ...)
TypeError: TypeAliasType.__init__() got an unexpected keyword argument '__pydantic_reset_parent_namespace__'
AssemblerError: Builder failed for element 'Observation.status':
TypeAliasType.__init__() got an unexpected keyword argument '__pydantic_reset_parent_namespace__'
Root Cause Analysis
The bug has two interrelated causes:
1. BackboneFieldBuilder.can_handle() fires on primitive fields with extension children
In backbone.py, can_handle() returns True whenever index.get_children(node.id) is non-empty:
def can_handle(self, node: ElementNode, index: DefinitionIndex) -> bool:
has_children = bool(index.get_children(node.id))
if has_children:
return True # ← fires for Observation.status when it has .extension children
...
When the differential contains Observation.status.extension and its slices, those elements are stored as children of Observation.status in the DefinitionIndex. This causes BackboneFieldBuilder to claim ownership of Observation.status, even though it is a primitive type (FHIR code), not a BackboneElement.
2. Primitive type's TypeAliasType is passed as a Pydantic __base__
BackboneFieldBuilder.build() then looks up backbone_base from the parent model's field annotation. For a primitive field like status, the annotation resolves to a TypeAliasType (e.g., ObservationStatus). When this is handed to pydantic.create_model(..., __base__=(TypeAliasType,)), Pydantic fails with the TypeError above.
3. Missing _ext placeholder awareness in the resolver/builder
Per the FHIR JSON serialization spec, extensions on primitive-type fields are serialized under the _<fieldname> sibling element (represented internally as <fieldname>_ext). The resolver and builder currently do not detect when Observation.status.extension children actually belong to the primitive extension placeholder (status_ext: Element) rather than the field itself. This accounting is already handled correctly for snapshot-derived models via build_primitive_extension_placeholder() in base.py, but it is not applied when processing differential elements that introduce extension slices on primitive fields.
Expected Behaviour
factory.build() should succeed and the generated model should:
- Keep
status as a primitive-type field (annotated with ObservationStatus / the appropriate code type).
- Emit a
status_ext / _status companion field (of type Element or a constrained subtype) that carries the extension slice information — consistent with the FHIR primitive extension mechanism already implemented in SimpleFieldBuilder and build_primitive_extension_placeholder().
Actual Behaviour
factory.build() raises:
AssemblerError: Builder failed for element 'Observation.status':
TypeAliasType.__init__() got an unexpected keyword argument '__pydantic_reset_parent_namespace__'
Likely Fix
BackboneFieldBuilder.can_handle() should guard against primitive-type nodes even when they have children. A node whose resolved FHIR kind is "primitive" (or whose annotation in the base model is not a subclass of BaseModel) should not be claimed by this builder.
- The differential resolver / assembler should detect when children of a primitive field are exclusively
extension/slice elements and, instead of building a backbone sub-model, route them through the existing build_primitive_extension_placeholder() path so the _ext companion field is enriched with the slice constraints.
When a
StructureDefinitiondifferential defines slices on theextensionof a primitive-type field (e.g.,Observation.status.extension:mySlice),FHIRModelFactory.build()raises anAssemblerErrorwrapping aTypeError:This is because
BackboneFieldBuilderincorrectly claims ownership of the primitive element (e.g.,Observation.status) once its extension slice children appear in the resolved index — then attempts to use the primitive'sTypeAliasType(e.g.,ObservationStatus) as a Pydantic__base__, which Pydantic rejects.Steps to Reproduce
Full Traceback
Root Cause Analysis
The bug has two interrelated causes:
1.
BackboneFieldBuilder.can_handle()fires on primitive fields with extension childrenIn backbone.py,
can_handle()returnsTruewheneverindex.get_children(node.id)is non-empty:When the differential contains
Observation.status.extensionand its slices, those elements are stored as children ofObservation.statusin theDefinitionIndex. This causesBackboneFieldBuilderto claim ownership ofObservation.status, even though it is a primitive type (FHIR code), not aBackboneElement.2. Primitive type's
TypeAliasTypeis passed as a Pydantic__base__BackboneFieldBuilder.build()then looks upbackbone_basefrom the parent model's field annotation. For a primitive field likestatus, the annotation resolves to aTypeAliasType(e.g.,ObservationStatus). When this is handed topydantic.create_model(..., __base__=(TypeAliasType,)), Pydantic fails with theTypeErrorabove.3. Missing
_extplaceholder awareness in the resolver/builderPer the FHIR JSON serialization spec, extensions on primitive-type fields are serialized under the
_<fieldname>sibling element (represented internally as<fieldname>_ext). The resolver and builder currently do not detect whenObservation.status.extensionchildren actually belong to the primitive extension placeholder (status_ext: Element) rather than the field itself. This accounting is already handled correctly for snapshot-derived models viabuild_primitive_extension_placeholder()in base.py, but it is not applied when processing differential elements that introduce extension slices on primitive fields.Expected Behaviour
factory.build()should succeed and the generated model should:statusas a primitive-type field (annotated withObservationStatus/ the appropriate code type).status_ext/_statuscompanion field (of typeElementor a constrained subtype) that carries the extension slice information — consistent with the FHIR primitive extension mechanism already implemented inSimpleFieldBuilderandbuild_primitive_extension_placeholder().Actual Behaviour
factory.build()raises:Likely Fix
BackboneFieldBuilder.can_handle()should guard against primitive-type nodes even when they have children. A node whose resolved FHIR kind is"primitive"(or whose annotation in the base model is not a subclass ofBaseModel) should not be claimed by this builder.extension/slice elements and, instead of building a backbone sub-model, route them through the existingbuild_primitive_extension_placeholder()path so the_extcompanion field is enriched with the slice constraints.