abpframework/abp · critical · AbpException
A connection name can not map to multiple databases: {mapped
Error message
A connection name can not map to multiple databases: {mappedConnection}. What it means
AbpDatabaseInfoDictionary.RefreshIndexes builds a reverse lookup from connection name -> AbpDatabaseInfo so that GetMappedDatabaseOrNull can resolve a connection string name to its owning database. As it iterates each database's MappedConnections, if a connection name was already registered by a different database it throws AbpException, because one connection name must map to at most one database. RefreshIndexes is invoked automatically by AbpDataModule.PostConfigureServices (AbpDataModule.cs:36), so this exception surfaces during application startup.
Source
Thrown at framework/src/Volo.Abp.Data/Volo/Abp/Data/AbpDatabaseInfoDictionary.cs:46
return this;
}
/// <summary>
/// This method should be called if this dictionary changes.
/// It refreshes indexes for quick access to the connection informations.
/// </summary>
public void RefreshIndexes()
{
ConnectionIndex = new Dictionary<string, AbpDatabaseInfo>();
foreach (var databaseInfo in Values)
{
foreach (var mappedConnection in databaseInfo.MappedConnections)
{
if (ConnectionIndex.ContainsKey(mappedConnection))
{
throw new AbpException(
$"A connection name can not map to multiple databases: {mappedConnection}."
);
}
ConnectionIndex[mappedConnection] = databaseInfo;
}
}
}
}
View on GitHub (pinned to 7ed43b1931)
Solutions
- Audit every database's MappedConnections and ensure each connection name appears in exactly one database; remove the duplicate from one side.
- If both databases legitimately need the connection, point them at a shared database entry instead of mapping the same connection name twice.
- Validate the configuration for duplicate mapped connections in your module configuration code before the framework calls RefreshIndexes, and fail fast with a clear message.
- Search appsettings.json and all Configure<AbpDbConnectionOptions> blocks for the offending connection name named in the exception message.
Example fix
// before: 'Saas1' mapped to two databases -> startup AbpException
Configure<AbpDbConnectionOptions>(options =>
{
options.Databases.Configure("App", db =>
{
db.MappedConnections.Add("Saas1");
});
options.Databases.Configure("Admin", db =>
{
db.MappedConnections.Add("Saas1"); // duplicate
});
});
// after: each connection name lives in only one database
Configure<AbpDbConnectionOptions>(options =>
{
options.Databases.Configure("App", db =>
{
db.MappedConnections.Add("Saas1");
});
options.Databases.Configure("Admin", db =>
{
db.MappedConnections.Add("Admin1"); // distinct name
});
}); Defensive patterns
Strategy: validation
Validate before calling
static void EnsureNoDuplicateMappedConnections(AbpDatabaseInfoDictionary databases)
{
var dup = databases.Values
.SelectMany(db => db.MappedConnections.Select(c => (db.DatabaseName, Connection: c)))
.GroupBy(x => x.Connection, StringComparer.OrdinalIgnoreCase)
.FirstOrDefault(g => g.Select(x => x.DatabaseName).Distinct().Count() > 1);
if (dup != null)
{
throw new ConfigurationException(
$"Connection '{dup.Key}' is mapped to multiple databases: " +
$"{string.Join(", ", dup.Select(x => x.DatabaseName))}.");
}
}
// call this right after configuring AbpDbConnectionOptions, before the framework boots. Try / catch
try
{
options.Databases.RefreshIndexes();
}
catch (Volo.Abp.AbpException ex) when (ex.Message.Contains("map to multiple databases"))
{
// RefreshIndexes runs in PostConfigureServices; catching here is for test/diagnostic harnesses.
throw new ConfigurationException($"Startup aborted: duplicate connection mapping. {ex.Message}", ex);
} Prevention
- Keep all database-to-connection mappings in one configuration section so duplicates are visible.
- Add a startup health check that asserts each MappedConnections entry is globally unique across databases.
- After merging modules, grep configured connection names for repeats before deploying.
- Treat the connection name as owned by exactly one database; document ownership per name.
When it happens
Trigger: Configuring AbpDbConnectionOptions.Databases so that two distinct databases both add the same connection name to their MappedConnections (e.g. database 'App' maps 'Saas1' and database 'Admin' also maps 'Saas1'). The throw fires during the module's PostConfigureServices phase when RefreshIndexes() rebuilds the index, aborting host initialization.
Common situations: Multi-database setups where connection-to-database mappings are configured in code (Configure<AbpDbConnectionOptions>) or via appsettings and a connection name was reused across databases by mistake; merging modules whose mapping configuration overlaps; copy-paste of a MappedConnections entry across two database blocks; refactor that moved a connection without removing the old mapping.
Related errors
- Both 'Period' and 'CronExpression' are not set for {worker.G
- Either Region or ServiceURL must be configured on AwsBlobPro
- The BLOB was encrypted with a tenant-specific passphrase, bu
- No BLOB Storage provider was registered! At least one provid
- Could not find an implementation of {typeof(IConfiguration).
AI-assisted analysis of abpframework/abp@7ed43b1931 (2026-08-13).
Data as JSON: /api/errors/4fbba9686c091365.
Report an issue: GitHub.