OrchardCMS/OrchardCore · error · InvalidOperationException
The configured table name separator
Error message
The configured table name separator '{tableNameSeparator}' is invalid. What it means
GetTableNameSeparator reads the shell setting 'TableNameSeparator' (or its default) and only accepts empty ('NULL' literal or empty => no separator) or strings composed solely of underscores. Any other character in the configured separator is rejected with InvalidOperationException, because table names are built by concatenating prefixes with this separator and invalid characters would corrupt SQL table names.
Solutions
- Set the separator to '_' (default), '__', or the literal string "NULL" for no separator.
- Remove invalid characters from TableNameSeparator in appsettings.json / tenant App_Data settings.
- Fix the DefaultTableNameSeparator in the shell configuration before tenant initialization.
Example fix
// before (appsettings.json)
"OrchardCore_Data_TableOptions": { "DefaultTableNameSeparator": "-" }
// after
"OrchardCore_Data_TableOptions": { "DefaultTableNameSeparator": "_" } // or "NULL" for none Defensive patterns
Strategy: validation
Validate before calling
var sep = config["OrchardCore_Data_TableOptions:DefaultTableNameSeparator"]?.Trim();
if (!string.IsNullOrEmpty(sep) && sep != "NULL" && sep.Any(c => c != '_'))
throw new InvalidOperationException($"TableNameSeparator '{sep}' invalid; use '_' characters or 'NULL'."); Type guard
bool IsValidSeparator(string s) { s = s?.Trim(); return string.IsNullOrEmpty(s) || s == "NULL" || s.All(c => c == '_'); } Try / catch
try { var opts = shellSettings.GetDatabaseTableOptions(); }
catch (InvalidOperationException ex) when (ex.Message.Contains("table name separator")) { _logger.LogCritical(ex, "Fix TableNameSeparator in tenant settings"); throw; } Prevention
- Validate table options in your deployment config pipeline before rollout.
- Only use '_' or the literal 'NULL' for the separator.
- Keep a shared appsettings template with known-good table options.
- Test tenant startup against staging config before production.
When it happens
Trigger: Configuring OrchardCore_Data_TableOptions:DefaultTableNameSeparator (appsettings.json or ShellSettings) with characters other than '_' or the literal 'NULL' — e.g. '-', '.', or a multi-character value like '__x' — then booting a tenant or calling GetDatabaseTableOptions().
Common situations: Copy-pasted config from another CMS using '-' separators; misunderstanding that only '_' or NULL are allowed; typos like '"__ "' with spaces (note settings are trimmed first).
Understand the failure class
Background: "Invalid value" and "allowed values are" config errors: what your library rejected and how to fix it — this error's family across 41 libraries.
Related errors
- The configured identity column size
- Unknown database provider:
- The 'OrchardCore.Shells.Database' configuration section…
- A feature is missing a mandatory 'Id' property in the Module
- Unsupported database provider
AI-assisted analysis of OrchardCMS/OrchardCore@4306c0717f (2026-09-13).
Data as JSON: /api/errors/951984d716b5401d.
Report an issue: GitHub.
Appendix: source
Thrown at src/OrchardCore/OrchardCore.Data.Abstractions/ShellSettingsExtensions.cs:66
public static string GetTableNameSeparator(this ShellSettings shellSettings)
{
var tableNameSeparator = (!shellSettings.IsInitialized()
? shellSettings[DefaultTableNameSeparator]
: shellSettings["TableNameSeparator"])
?.Trim();
if (string.IsNullOrEmpty(tableNameSeparator))
{
tableNameSeparator = "_";
}
else if (tableNameSeparator == "NULL")
{
tableNameSeparator = string.Empty;
}
else if (tableNameSeparator.Any(c => c != '_'))
{
throw new InvalidOperationException($"The configured table name separator '{tableNameSeparator}' is invalid.");
}
return tableNameSeparator;
}
public static string GetIdentityColumnSize(this ShellSettings shellSettings)
{
var identityColumnSize = (!shellSettings.IsInitialized()
? shellSettings[DefaultIdentityColumnSize]
: shellSettings["IdentityColumnSize"])
?.Trim();
if (string.IsNullOrEmpty(identityColumnSize))
{
identityColumnSize = !shellSettings.IsInitialized() ? nameof(Int64) : nameof(Int32);
}
else if (!s_identityColumnSizes.Contains(identityColumnSize))
{View on GitHub (pinned to 4306c0717f)