fullstackhero/dotnet-starter-kit · error · InvalidOperationException

ConnectionString can't be null.

Error message

ConnectionString can't be null.

What it means

The explicit IAppTenantInfo.ConnectionString setter on AppTenantInfo accepts only non-null values; assigning null throws InvalidOperationException("ConnectionString can't be null."). Finbuckle uses this interface property when resolving a tenant's database connection string, so a null there would break tenant store initialization.

Solutions

  1. Set an explicit empty string instead of null if the tenant uses the shared database.
  2. Check tenant.ConnectionString for null before assigning through IAppTenantInfo.ConnectionString.
  3. Ensure seeded/created tenants have ConnectionString populated when per-tenant databases are required.
  4. Fix the tenant store/resolver code so it only writes non-null connection strings.

Example fix

// before
tenantInfo.ConnectionString = maybeNullFromDb; // throws if null

// after
if (maybeNullFromDb is not null)
    ((IAppTenantInfo)tenantInfo).ConnectionString = maybeNullFromDb;
Defensive patterns

Strategy: type-guard

Validate before calling

if (tenant.ConnectionString is null)
    throw new InvalidOperationException("Tenant connection string must be set before assignment.");

Type guard

bool HasConnectionString(AppTenantInfo t) => !string.IsNullOrEmpty(t.ConnectionString);

Try / catch

try {
    ((IAppTenantInfo)tenantInfo).ConnectionString = resolved;
} catch (InvalidOperationException ex) when (ex.Message.Contains("ConnectionString")) {
    logger.LogError("Tenant {TenantId} has a null connection string", tenantInfo.Id);
}

Prevention

When it happens

Trigger: Finbuckle's tenant store or mapping code assigning null to IAppTenantInfo.ConnectionString — typically a tenant entity whose ConnectionString is null while the resolver tries to set it, or code calling the setter with a null connection string.

Common situations: Tenants created without a connection string (falling back to the shared database) then passed through a resolver that writes the property; deserialization of tenant data with a missing ConnectionString field; migrations/seed copying tenants between stores with nulls.

Related errors


AI-assisted analysis of fullstackhero/dotnet-starter-kit@3f2959e683 (2026-09-15). Data as JSON: /api/errors/243759f05b2aaf02. Report an issue: GitHub.

Appendix: source

Thrown at src/BuildingBlocks/Shared/Multitenancy/AppTenantInfo.cs:84

        }

        IsActive = true;
    }

    public void Deactivate()
    {
        if (Id == MultitenancyConstants.Root.Id)
        {
            throw new InvalidOperationException("Invalid Tenant");
        }

        IsActive = false;
    }

    string? IAppTenantInfo.ConnectionString
    {
        get => ConnectionString;
        set => ConnectionString = value ?? throw new InvalidOperationException("ConnectionString can't be null.");
    }
}

View on GitHub (pinned to 3f2959e683)