🐛 Bug Report
Description
Resource validation operations are failing with NullReferenceException in the ParameterCompatibleFilter.ParseResource() method when processing Parameters resources that don't contain the expected "resource" parameter.
Error Details
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.Health.Fhir.Api.Features.Filters.ParameterCompatibleFilter.ParseResource(Resource resource)
in /_/src/Microsoft.Health.Fhir.Shared.Api/Features/Filters/ParameterCompatibleFilter.cs:line 26
at Microsoft.Health.Fhir.Api.Features.Filters.ValidateResourceTypeFilterAttribute.OnActionExecuting(ActionExecutingContext context)
in /_/src/Microsoft.Health.Fhir.Shared.Api/Features/Filters/ValidateResourceTypeFilterAttribute.cs:line 33
Root Cause Analysis
The issue occurs in ParameterCompatibleFilter.cs line 26:
protected Resource ParseResource(Resource resource)
{
if (_allowParametersResource && resource.TypeName == KnownResourceTypes.Parameters)
{
resource = ((Parameters)resource).Parameter.Find(param => param.Name.Equals("resource", StringComparison.OrdinalIgnoreCase)).Resource; // LINE 26 - NULL REFERENCE
}
return resource;
}
The issue occurs when:
resource.TypeName == KnownResourceTypes.Parameters is true
((Parameters)resource).Parameter.Find(...) returns null because:
- No parameter with name "resource" exists
- The Parameter collection is null
- The found parameter has a null Resource property
- Accessing
.Resource on a null parameter causes the NullReferenceException
Reproduction Steps
- Create a Parameters resource with either:
- No parameter named "resource"
- A parameter named "resource" with a null Resource property
- A null Parameter collection
- Send this Parameters resource through the validation pipeline
- The NullReferenceException will be thrown at line 26
Minimal Reproduction Example
var parameters = new Parameters();
parameters.Parameter = new List<Parameters.ParameterComponent>
{
new Parameters.ParameterComponent
{
Name = "resource",
Resource = null // This causes the NullReferenceException
}
};
// This will throw NullReferenceException when processed by ParameterCompatibleFilter
Proposed Fix
Add defensive null checking in the ParseResource method:
protected Resource ParseResource(Resource resource)
{
if (_allowParametersResource && resource?.TypeName == KnownResourceTypes.Parameters)
{
var parameters = (Parameters)resource;
var resourceParam = parameters.Parameter?.Find(param => param.Name.Equals("resource", StringComparison.OrdinalIgnoreCase));
if (resourceParam?.Resource != null)
{
resource = resourceParam.Resource;
}
// If no resource parameter found or it's null, return the original Parameters resource
// This maintains backward compatibility while preventing the crash
}
return resource;
}
Alternative Solution
Add validation in the calling methods to handle null results from ParseResource():
public override void OnActionExecuting(ActionExecutingContext context)
{
// ... existing code ...
if (context.ActionArguments.TryGetValue(KnownActionParameterNames.Resource, out var parsedModel))
{
var resource = ParseResource((Resource)parsedModel);
if (resource == null)
{
throw new ResourceNotValidException("Failed to extract resource from Parameters");
}
ValidateType(resource, (string)actionModelType);
}
}
Test Cases to Add
[Fact]
public void ParseResource_WithNullParameterResource_ShouldNotThrow()
{
var parameters = new Parameters();
parameters.Parameter = new List<Parameters.ParameterComponent>
{
new Parameters.ParameterComponent { Name = "resource", Resource = null }
};
var filter = new TestParameterCompatibleFilter(allowParametersResource: true);
var result = filter.ParseResource(parameters);
Assert.NotNull(result); // Should not throw NullReferenceException
}
[Fact]
public void ParseResource_WithMissingResourceParameter_ShouldNotThrow()
{
var parameters = new Parameters();
parameters.Parameter = new List<Parameters.ParameterComponent>
{
new Parameters.ParameterComponent { Name = "otherParam", Value = new FhirString("test") }
};
var filter = new TestParameterCompatibleFilter(allowParametersResource: true);
var result = filter.ParseResource(parameters);
Assert.NotNull(result); // Should not throw NullReferenceException
}
Impact
- Severity: High - Validation operations fail with HTTP 500 errors
- Affected Operations: Resource validation endpoints that accept Parameters resources
- Client Impact: Any client sending Parameters resources without proper "resource" parameter structure
Backward Compatibility
The proposed fix maintains backward compatibility by:
- Still extracting the inner resource when properly structured Parameters are provided
- Gracefully handling malformed Parameters by returning the original Parameters resource
- Not changing the method signature or expected behavior for valid inputs
This is a defensive programming issue where the code assumes Parameters resources always contain a valid "resource" parameter. The fix should prevent crashes while maintaining existing functionality.
🐛 Bug Report
Description
Resource validation operations are failing with
NullReferenceExceptionin theParameterCompatibleFilter.ParseResource()method when processing Parameters resources that don't contain the expected "resource" parameter.Error Details
Root Cause Analysis
The issue occurs in
ParameterCompatibleFilter.csline 26:The issue occurs when:
resource.TypeName == KnownResourceTypes.Parametersis true((Parameters)resource).Parameter.Find(...)returns null because:.Resourceon a null parameter causes the NullReferenceExceptionReproduction Steps
Minimal Reproduction Example
Proposed Fix
Add defensive null checking in the
ParseResourcemethod:Alternative Solution
Add validation in the calling methods to handle null results from
ParseResource():Test Cases to Add
Impact
Backward Compatibility
The proposed fix maintains backward compatibility by:
This is a defensive programming issue where the code assumes Parameters resources always contain a valid "resource" parameter. The fix should prevent crashes while maintaining existing functionality.