Skip to content

Troubleshooting

Quick answers to the most common Domain Services errors.


401 Unauthorized

Cause: The request has no Authorization header, the token has expired, or the token was issued for a different audience/issuer.

Fix: 1. Obtain a fresh token from your Authorization Server (POST /api/tokens). 2. Confirm Tokens:Issuer and Tokens:Audience match between the Auth Server and the Web API's appsettings.json. 3. For local development, register AllowAnonymousHandler to bypass auth entirely (see Authentication & JWT Setup).

Warning: Remove AllowAnonymousHandler before any production deployment.


Could not load type 'DHI.Services...'

Cause: The RepositoryType (or $type) value in connections.json doesn't match the assembly-qualified name of an installed package. This happens after a package update, a rename, or a typo.

Fix: 1. Check the exact type name in the installed package. The format is Namespace.ClassName, AssemblyName. 2. Confirm the NuGet package that owns the type is installed in the project. 3. Confirm the assembly name matches the NuGet package ID (they're usually the same, but not always).

Example of a correct RepositoryType:

"RepositoryType": "DHI.Services.Provider.PostgreSQL.ScalarRepository, DHI.Services.Provider.PostgreSQL"


KeyNotFoundException on service lookup

Cause: ServiceLocator.Get<T>("connectionId") was called with a connectionId that has no matching registration.

Common scenarios: - The connections.json entry uses a different key than what the route passes. - The imperative ServiceLocator.Register(...) call was never reached (e.g., inside a conditional or after an early return). - LazyCreation is true but the connections.json file is missing or malformed.

Fix: 1. Verify the connectionId in the URL matches exactly the key in connections.json or the second argument in ServiceLocator.Register(service, "key"). 2. Call GET /api/services to list all currently registered service IDs. 3. Check that Services.Configure(...) is called before any requests arrive.


SignalR / IFilterRepository errors

Cause: IFilterRepository is not registered in DI. Time Series and Jobs Web API packages require this registration even if you don't use SignalR filtering.

Fix: Add to Program.cs:

builder.Services.AddSingleton<IFilterRepository>(
    new FilterRepository("[AppData]signalr-filters.json".Resolve())
);

The file signalr-filters.json does not need to exist — the registration just satisfies DI. If you also see SignalR hub connection errors, add:

builder.Services.AddSignalR();

[AppData] path not resolving

Cause: "[AppData]path".Resolve() replaces [AppData] with the value of AppDomain.CurrentDomain.GetData("DataDirectory"). If that key hasn't been set, the path is returned as-is and the file won't be found.

Fix: Set DataDirectory early in Program.cs:

AppDomain.CurrentDomain.SetData("DataDirectory",
    Path.Combine(AppContext.BaseDirectory, "App_Data"));

The BaseWebApi template does this automatically. If you're starting from scratch, add this line before any service registration.


InvalidOperationException: Type not found (in IConnection.Create)

Cause: A connections.json entry has a RepositoryType that points to a type whose assembly isn't loaded into the process. This often happens when the provider NuGet package is installed but the assembly isn't referenced anywhere in startup code.

Fix: Force the assembly to load by adding a dummy reference in Program.cs:

// Force-load the provider assembly so connections.json can resolve its types
_ = typeof(DHI.Services.Provider.PostgreSQL.ScalarRepository).Assembly;

Or add CopyLocalLockFileAssemblies to your .csproj if the assembly is being stripped.