{"record":{"id":"9744198feb3203ea","repo":"microsoft/aspire","slug":"the-azure-parameter-azurebicepresource-knownparameters","errorCode":null,"errorMessage":"The Azure parameter '{AzureBicepResource.KnownParameters.PrincipalType}' must be supplied when '{AzureBicepResource.KnownParameters.UserPrincipalId}' is provided explicitly.","messagePattern":"The Azure parameter '(.+?)' must be supplied when '(.+?)' is provided explicitly\\.","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/Aspire.Hosting.Azure/Provisioning/Provisioners/BicepProvisioner.cs","lineNumber":1420,"sourceCode":"            // Published artifacts bind this deployment-principal parameter from the outer\n            // main.bicep template. Direct `aspire deploy` has no outer template, so use the\n            // authenticated principal that performs the data-plane deployment.\n            resource.Parameters[AzureBicepResource.KnownParameters.UserPrincipalId] = context.Principal.Id;\n            populatedUserPrincipalId = true;\n        }\n\n        if (resource.Parameters.TryGetValue(AzureBicepResource.KnownParameters.PrincipalName, out var principalName) && principalName is null)\n        {\n            ValidateUnknownPrincipalParameter(context);\n\n            resource.Parameters[AzureBicepResource.KnownParameters.PrincipalName] = context.Principal.Name;\n        }\n\n        if (resource.Parameters.TryGetValue(AzureBicepResource.KnownParameters.PrincipalType, out var principalType) && principalType is null)\n        {\n            if (hasUserPrincipalId && !populatedUserPrincipalId)\n            {\n                throw new InvalidOperationException(\n                    $\"The Azure parameter '{AzureBicepResource.KnownParameters.PrincipalType}' must be supplied when \" +\n                    $\"'{AzureBicepResource.KnownParameters.UserPrincipalId}' is provided explicitly.\");\n            }\n\n            if (!hasUserPrincipalId)\n            {\n                ValidateUnknownPrincipalParameter(context);\n            }\n\n            // Use the principal type detected from the credential's access token (the `idtyp`\n            // claim) instead of hardcoding \"User\". A hardcoded \"User\" caused the role-assignment\n            // `-roles` deployments synthesized by AzureResourcePreparer to fail with\n            // `UnmatchedPrincipalType` / `PrincipalNotFound` whenever the AppHost ran under a\n            // service-principal / federated-workload-identity credential (CI, CD, deploy bots).\n            // See https://github.com/microsoft/aspire/issues/13933.\n            resource.Parameters[AzureBicepResource.KnownParameters.PrincipalType] = context.Principal.Type;\n        }\n","sourceCodeStart":1402,"sourceCodeEnd":1438,"githubUrl":"https://github.com/microsoft/aspire/blob/25830f84bd145686607ad00c057b3f84e2e51d43/src/Aspire.Hosting.Azure/Provisioning/Provisioners/BicepProvisioner.cs#L1402-L1438","documentation":"A UserPrincipalId parameter was supplied explicitly (not auto-populated by Aspire) but PrincipalType was not. Bicep role assignments need both the principal id and its type (User/ServicePrincipal/Group), so the provisioner throws rather than guessing.","triggerScenarios":"Setting resource.Params[AzureBicepResource.KnownParameters.UserPrincipalId] manually (e.g. from config) while leaving KnownParameters.PrincipalType unset, and PrincipalType is present-but-null in Parameters.","commonSituations":"Hardcoding a user principal id for local testing; copying parameter setup that only set the id; the type parameter declared in the module but never assigned.","solutions":["Also set resource.Params[AzureBicepResource.KnownParameters.PrincipalType] (e.g. \"User\") whenever you set UserPrincipalId.","Remove the explicit UserPrincipalId and let Aspire bind the deployment principal automatically.","Load both values from configuration together so they stay in sync.","Prefer AddAzureContainerAppEnvironment which populates principal parameters for you."],"exampleFix":"// before\nresource.Params[AzureBicepResource.KnownParameters.UserPrincipalId] = userId;\n// after\nresource.Params[AzureBicepResource.KnownParameters.UserPrincipalId] = userId;\nresource.Params[AzureBicepResource.KnownParameters.PrincipalType] = \"User\";","handlingStrategy":"validation","validationCode":"bool hasUpid = resource.Parameters.TryGetValue(AzureBicepResource.KnownParameters.UserPrincipalId, out var upid) && upid is not null;\nbool hasType = resource.Parameters.TryGetValue(AzureBicepResource.KnownParameters.PrincipalType, out var ptype) && ptype is not null;\nif (hasUpid && !hasType) throw new InvalidOperationException(\"PrincipalType must accompany UserPrincipalId.\");","typeGuard":null,"tryCatchPattern":"try { await provisioner.ProvisionAsync(...); } catch (InvalidOperationException ex) when (ex.Message.Contains(\"PrincipalType\")) { logger.LogError(ex, \"Set KnownParameters.PrincipalType alongside UserPrincipalId\"); throw; }","preventionTips":["Set UserPrincipalId and PrincipalType together from one config source.","Prefer letting Aspire bind the deployment principal instead of manual ids.","Add a pre-publish parameter sanity check in your AppHost."],"tags":["azure","bicep","provisioning","role-assignment","parameters"],"backgroundTag":"missing-required-argument","analyzedSha":"25830f84bd145686607ad00c057b3f84e2e51d43","analyzedAt":"2026-09-16T11:10:06.193Z","contentChangedAt":"2026-09-16T11:10:06.193Z","schemaVersion":2},"datasetVersion":"2026-09-21T04:17:39.646Z"}