dotnet/orleans · critical · InvalidOperationException
WEBSITE_PRIVATE_PORTS must contain at least one TCP port.
Error message
WEBSITE_PRIVATE_PORTS must contain at least one TCP port.
What it means
An InvalidOperationException thrown by the Azure App Service silo host when the WEBSITE_PRIVATE_PORTS setting is missing or its first comma-separated value cannot be parsed as a TCP port. Azure App Service injects WEBSITE_PRIVATE_PORTS to tell the silo which private ports to bind; the code parses the first as the silo port with NumberStyles.None (unsigned integer). If parsing fails or the array is empty, startup aborts.
Source
Thrown at samples/Deployment/AzureAppService/Silo/Program.cs:109
app.MapBlazorHub();
app.MapFallbackToPage("/_Host");
await app.RunAsync();
static void ConfigureProductionOrleans(WebApplicationBuilder builder)
{
var clusterId = GetRequiredSetting(builder, "ORLEANS_CLUSTER_ID");
var serviceId = GetRequiredSetting(builder, "ORLEANS_SERVICE_ID");
var storageUri = new Uri(GetRequiredSetting(builder, "ORLEANS_AZURE_STORAGE_URI"));
var managedIdentityClientId = GetRequiredSetting(builder, "AZURE_CLIENT_ID");
var privateIp = IPAddress.Parse(GetRequiredSetting(builder, "WEBSITE_PRIVATE_IP"));
var privatePorts = GetRequiredSetting(builder, "WEBSITE_PRIVATE_PORTS")
.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (privatePorts.Length < 1
|| !int.TryParse(privatePorts[0], NumberStyles.None, CultureInfo.InvariantCulture, out var siloPort))
{
throw new InvalidOperationException(
"WEBSITE_PRIVATE_PORTS must contain at least one TCP port.");
}
var credential = new DefaultAzureCredential(new DefaultAzureCredentialOptions
{
ManagedIdentityClientId = managedIdentityClientId,
});
var tableServiceClient = new TableServiceClient(storageUri, credential);
builder.UseOrleans(siloBuilder =>
{
siloBuilder
.Configure<SiloOptions>(options =>
{
options.SiloName = builder.Configuration["WEBSITE_INSTANCE_ID"]
?? Environment.MachineName;
})
.Configure<ClusterOptions>(options =>View on GitHub (pinned to fca799fa70)
Solutions
- Deploy/run the silo inside an Azure App Service so the platform injects WEBSITE_PRIVATE_PORTS automatically.
- If running locally, set WEBSITE_PRIVATE_PORTS to a valid port (e.g., '11111') in environment/launchSettings for testing.
- Verify the value has no stray characters/signs — NumberStyles.None rejects '+','-', whitespace, and hex.
Example fix
// before
if (privatePorts.Length < 1
|| !int.TryParse(privatePorts[0], NumberStyles.None, CultureInfo.InvariantCulture, out var siloPort))
{
throw new InvalidOperationException("WEBSITE_PRIVATE_PORTS must contain at least one TCP port.");
}
// after (explicit, actionable error)
if (privatePorts.Length < 1)
throw new InvalidOperationException("WEBSITE_PRIVATE_PORTS is empty; configure at least one private TCP port in the App Service.");
if (!int.TryParse(privatePorts[0], NumberStyles.None, CultureInfo.InvariantCulture, out var siloPort))
throw new InvalidOperationException($"WEBSITE_PRIVATE_PORTS[0] = '{privatePorts[0]}' is not a valid TCP port."); Defensive patterns
Strategy: validation
Validate before calling
var raw = builder.Configuration["WEBSITE_PRIVATE_PORTS"];
var ports = raw?.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (ports is null || ports.Length == 0 || !int.TryParse(ports[0], NumberStyles.None, CultureInfo.InvariantCulture, out _))
throw new InvalidOperationException("WEBSITE_PRIVATE_PORTS must contain at least one TCP port."); Prevention
- Run the silo inside Azure App Service so the platform injects WEBSITE_PRIVATE_PORTS.
- For local tests, set the variable explicitly to a valid port.
- Avoid non-numeric characters; NumberStyles.None rejects signs/whitespace/hex.
When it happens
Trigger: Silo startup in an Azure App Service where WEBSITE_PRIVATE_PORTS is unset, empty, or contains a non-numeric/signed value in position 0. The Split + int.TryParse(NumberStyles.None) guard catches both 'no ports' and 'unparseable port'.
Common situations: Running the sample outside Azure App Service (the env var is never set). A corrupted/misconfigured app setting. The App Service plan variant not injecting the variable as expected.
Related errors
- The required setting '{name}' isn't configured.
- AzureTable:ServiceUri must be an absolute HTTPS Azure Table
- AZURE_CLIENT_ID must contain the user-assigned managed ident
- Configure AzureTable:ServiceUri for Azure, or use Azurite wi
- {key} is not configured.
AI-assisted analysis of dotnet/orleans@fca799fa70 (2026-08-13).
Data as JSON: /api/errors/65838bbdc8b3c868.
Report an issue: GitHub.