OrchardCMS/OrchardCore · error · InvalidOperationException
The 'Default' tenant can't be removed.
Error message
The 'Default' tenant can't be removed.
What it means
CheckCanRemoveShell throws InvalidOperationException because the Default tenant is the root shell of an Orchard Core application and can never be removed. The check runs before RemoveShellSettingsAsync/RemoveShellContextAsync perform any deletion.
Solutions
- Exclude the Default tenant before calling the remove APIs (check settings.IsDefaultShell() or settings.Name == "Default").
- If the goal is to reset Default, disable/reconfigure it instead of removing it.
- Fix the caller to pass the correct ShellSettings instance.
Example fix
// before
await _shellHost.RemoveShellSettingsAsync(settings);
// after
if (!settings.IsDefaultShell())
{
await _shellHost.RemoveShellSettingsAsync(settings);
} Defensive patterns
Strategy: validation
Validate before calling
if (settings.IsDefaultShell() || settings.Name == ShellSettings.DefaultShellName)
{
throw new InvalidOperationException("The Default tenant cannot be removed.");
} Prevention
- Always exclude the 'Default' tenant from delete loops and cleanup jobs.
- Use settings.IsDefaultShell() as a precondition check before any removal call.
When it happens
Trigger: Calling RemoveShellSettingsAsync or RemoveShellContextAsync with the settings of the 'Default' tenant (ShellSettings.DefaultShellName).
Common situations: Bulk tenant-cleanup scripts that iterate all tenants without excluding Default; admin UI/logic bugs passing the wrong tenant; recipes or migrations attempting to delete the Default tenant.
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
- The tenant ' ' can't be removed as it is neither…
- Unable to reload the tenant
- Unexpected shell state for
- File path must be a non-empty string.
- Can't resolve a scope on tenant
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/f2cc0e5f33e3c59f.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore/Shell/ShellHost.cs:517
shellSettings.IsRunning() ||
shellSettings.IsUninitialized() ||
shellSettings.IsInitializing();
/// <summary>
/// Whether or not a shell can be released and removed from the list, false if disabled and still in use.
/// Note: A disabled shell still in use will be released by its last scope, and keeping it in the list
/// prevents a consumer from creating a new one that would have a null service provider.
/// </summary>
private bool CanReleaseShell(ShellSettings settings) => !settings.IsDisabled() || !IsShellActive(settings);
/// <summary>
/// Checks if a shell can be removed, throws an exception if the shell is neither uninitialized nor disabled.
/// </summary>
private void CheckCanRemoveShell(ShellSettings settings)
{
if (settings.IsDefaultShell())
{
throw new InvalidOperationException($"The '{ShellSettings.DefaultShellName}' tenant can't be removed.");
}
// A disabled shell may be still in use in at least one active scope.
if (!settings.IsRemovable() || IsShellActive(settings))
{
throw new InvalidOperationException(
$"The tenant '{settings.Name}' can't be removed as it is neither uninitialized nor disabled.");
}
}
/// <summary>
/// Whether or not a shell is in use in at least one active scope.
/// </summary>
private bool IsShellActive(ShellSettings settings) =>
settings is { Name: not null } &&
_shellContexts.TryGetValue(settings.Name, out var context) &&
context.IsActive();
View on GitHub (pinned to 4306c0717f)