microsoft/aspire · error · ArgumentException
'ownerResource' and 'identityResource' must both be null…
Error message
'ownerResource' and 'identityResource' must both be null (for global role assignments) or both be non-null (for targeted role assignments).
What it means
AzureRoleAssignmentResource enforces that role assignments are either global (attached to no owner resource) or targeted (attached to a specific owner resource). ValidateOwnerAndIdentity throws ArgumentException when exactly one of ownerResource/identityResource is null, because the constructor factory APIs require the pair to be consistent. The exception names whichever argument is null to point at the mismatched half.
Solutions
- Ensure both ownerResource and identityResource are provided together for targeted role assignments.
- If the role assignment should be global, pass null for both arguments.
- Check custom wrapper/extension methods that may pass the identity conditionally and make the null-ness symmetric.
Example fix
// before
var roles = new AzureRoleAssignmentResource("roles", scopeGroup, ownerResource, null);
// after
var roles = new AzureRoleAssignmentResource("roles", scopeGroup, ownerResource, identityResource); Defensive patterns
Strategy: validation
Validate before calling
if ((ownerResource is null) != (identityResource is null))
{
throw new ArgumentException("ownerResource and identityResource must both be null or both non-null.");
} Type guard
bool isValidPair = (ownerResource is null && identityResource is null) || (ownerResource is not null && identityResource is not null);
Try / catch
try { /* construct role assignment */ } catch (ArgumentException ex) when (ex.Message.Contains("ownerResource")) { /* fix call site: pass both or neither */ } Prevention
- Always obtain the identity from the same builder call chain that produces the owner resource.
- Never construct AzureRoleAssignmentResource directly; use the public WithRoleAssignments extension APIs.
When it happens
Trigger: Calling the AzureRoleAssignmentResource constructor (or WithRoleAssignments-style APIs that feed it) with an ownerResource but a null identityResource, or vice versa.
Common situations: Hand-constructing role assignment resources in custom extension methods; refactoring code that passes an identity only conditionally; mixing the global API surface (no owner) with an identity parameter by mistake.
Understand the failure class
Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.
Related errors
- Address prefix must be a string or a parameter resource…
- Address prefix must be omitted, a string, or a parameter…
- An Azure principal parameter was not supplied a value…
- At least one partition key path should be provided.
- Invalid Event Hubs role
AI-assisted analysis of microsoft/aspire@25830f84bd (2026-09-16).
Data as JSON: /api/errors/9be540dddb293e12.
Report an issue: GitHub.
Appendix: source
Thrown at src/Aspire.Hosting.Azure/AzureRoleAssignmentResource.cs:59
/// <remarks>
/// This is the resource on which <c>WithRoleAssignments</c> was called. Its managed identity
/// is exposed via <see cref="IdentityResource"/>.
/// When <c>WithRoleAssignments</c> is called using an <see cref="AzureUserAssignedIdentityResource"/>,
/// OwnerResource and IdentityResource are the same.
/// </remarks>
public IResource? OwnerResource { get; } = ValidateOwnerAndIdentity(ownerResource, identityResource);
/// <summary>
/// Gets the user-assigned managed identity whose principal receives the role assignments,
/// or <see langword="null"/> for global role assignments that are granted to the deployment principal.
/// </summary>
public AzureUserAssignedIdentityResource? IdentityResource { get; } = identityResource;
private static IResource? ValidateOwnerAndIdentity(IResource? ownerResource, AzureUserAssignedIdentityResource? identityResource)
{
if ((ownerResource is null) != (identityResource is null))
{
throw new ArgumentException(
$"'{nameof(ownerResource)}' and '{nameof(identityResource)}' must both be null (for global role assignments) or both be non-null (for targeted role assignments).",
ownerResource is null ? nameof(ownerResource) : nameof(identityResource));
}
return ownerResource;
}
}
View on GitHub (pinned to 25830f84bd)