Skip to content
StarLive demo →
ReferenceChecked against main · 31 Oct 20268 min read

Troubleshooting

Symptom, cause and fix for AppointMe problems in local .NET 10 development. Docker, dev certificates, Aspire, Keycloak, SQL Server, Mailpit, the Vite+ dev server, API client generation and 403s.

Each row starts from what you see: an error message, a log line or a behavior. Messages in code font are quoted from the AppointMe source or from the tool that prints them (Docker, .NET, Keycloak, SQL Server or Vite), and rows are sorted alphabetically within each area. For the normal setup, start with the Quick start; for ports and volumes, see Local services & ports.

Aspire and Compose share host ports, and their data lives in named volumes. Most Docker problems come from one of those two facts.

Symptom Cause Fix
Bind for 0.0.0.0:60740 failed: port is already allocated (or 8082, 8026, 1026) Aspire’s persistent containers and the Compose containers claim the same host ports. Aspire’s keep running after you stop the AppHost. Stop one set: docker compose stop, or stop the Aspire containers in Docker. docker ps shows which holds the port.
Containers never start, or docker compose can’t connect to the Docker daemon Docker isn’t running Start Docker and check with docker info
Data is still there after docker compose down down keeps the sqlserver-data and keycloak-data volumes docker compose down -v removes them too
Keycloak never turns healthy under Compose docker/keycloak/certs/keycloak.crt or keycloak.key is missing, and compose.yaml mounts both Run ./docker/keycloak/export-dev-cert.sh, then docker compose up -d --force-recreate keycloak. If either path exists as an empty folder, Docker created it on the first up: delete it, then export.

The API and Keycloak use the ASP.NET Core dev certificate. The AppHost checks it before it starts anything.

Symptom Cause Fix
The AppHost exits with error: the ASP.NET Core HTTPS development certificate is missing or not trusted. dotnet dev-certs https --check --trust failed on Windows or macOS dotnet dev-certs https --trust. If a certificate exists but is still untrusted, run dotnet dev-certs https --clean first.
Keycloak under Compose serves a certificate the browser or the API rejects The dev certificate isn’t trusted, or you regenerated it (for example with --clean) after exporting, so keycloak.crt is stale Run ./docker/keycloak/export-dev-cert.sh again, which trusts and then exports, then docker compose up -d --force-recreate keycloak
Login fails with an unexplained 500 The certificate wasn’t trusted, so Aspire served Keycloak over plain HTTP. On Linux the AppHost only warns about this. Trust the certificate, then restart the AppHost
warning: the HTTPS development certificate is missing or not trusted. Run 'dotnet dev-certs https --trust' if HTTPS fails. Linux has no single trust store the tool can check, so the AppHost warns and carries on If HTTPS then fails, trust the certificate the way your distribution needs: see Enforce HTTPS in ASP.NET Core

Aspire starts resources in dependency order. The API reads its required settings at startup and stops with a named error if one is missing.

Symptom Cause Fix
appointme-api stays in Waiting It waits for SQL Server, Keycloak and Mailpit. The first run also pulls three images and imports the realm. Wait, or open each container’s logs in the Aspire dashboard
appointme-frontend fails to start Node.js is older than 22.18, which Vite+ 1.4 requires Install Node 24, the version in src/AppointMe.Frontend/.node-version
The Aspire dashboard asks for a token You opened https://localhost:17082 without the token the AppHost generated Use the dashboard URL the AppHost prints in its console
The generated solution doesn’t compile dotnet new appointme -n got a name that isn’t a dotted identifier, such as my-booking-app. dotnet new still reports success. Generate again with a name like Contoso.Booking
Section 'Authentication:Keycloak' not found in configuration. The API started outside the Development environment, for example with --no-launch-profile. That section exists only in appsettings.Development.json. Use --launch-profile https, or set ASPNETCORE_ENVIRONMENT=Development
Unknown Wolverine:Transport '…'. Expected 'SqlDurable' or 'AzureServiceBus'. A typo in Wolverine:Transport Use one of the two values

Keycloak imports its realm once and keeps it in a volume. Its email goes to Mailpit, whose web UI is on host port 8026.

Symptom Cause Fix
A new KC_BOOTSTRAP_ADMIN_PASSWORD has no effect Keycloak creates the bootstrap admin only on the first start of an empty database Change the password in the admin console, or remove the Keycloak volume
Changes to appointme-realm.json don’t show up The realm already exists in Keycloak’s data volume, so the import skips it Remove the Keycloak container and its volume (AppointMe-Keycloak under Aspire, appointme_keycloak-data under Compose). This also deletes local users.
“Continue with Google” fails The realm’s google identity provider has an empty client secret Configure your own Google OAuth client in the realm, or remove the provider and the button
Invalid parameter: redirect_uri The sign-in started from an origin the realm doesn’t list. Its clients allow redirects only to https://localhost:5173 and https://localhost:7233. Open the app on https://localhost:5173 and run the API with --launch-profile https. To use other ports, add them to the clients’ redirect URIs in the realm.
Symptom Cause Fix
Emails are gone Mailpit has no volume, so recreating its container empties it Expected. Sign up again to get a new email.
No verification email arrives You opened port 8025, which is Mailpit’s container port, or Keycloak can’t resolve the Mailpit host Open http://localhost:8026. Under Compose, keep the Mailpit network alias on the mailpit service.

SQL Server listens on host port 60740, and each module keeps its tables in its own schema.

Symptom Cause Fix
A network-related or instance-specific error occurred while establishing a connection to SQL Server. Nothing is listening on localhost,60740 Under Compose, check docker compose ps for a healthy sqlserver. Under Aspire, the API waits for it.
A SQL client rejects the server’s certificate The container uses a self-signed certificate Turn on “Trust server certificate”, as the connection string does with TrustServerCertificate=True
Login failed for user 'sa'. after you changed the password SQL Server sets the sa password when the data volume is first initialized Change it back, or remove the SQL Server volume. Migrations recreate the schema.
Module tables aren’t in dbo Each module has its own schema Look in identity, organizations, crm, booking and hangfire. Wolverine’s wolverine_* tables are in dbo at this commit.

The dev server proxies the API, and CI enforces Oxfmt formatting. Generated client files are never edited by hand.

Symptom Cause Fix
An editor formats files differently from CI The editor still uses Prettier or ESLint. There’s no .prettierrc or eslint.config.js; the rules live in vite.config.ts. Use the Oxc plugin (JetBrains) or the VoidZero.vite-plus-extension-pack (VS Code), or run npm run format
npm install rewrote package-lock.json Your npm differs from the npm 11 that wrote the lockfile Use npm ci, and discard the lockfile change
npm run check fails in CI Oxfmt formatting is enforced, as are Oxlint’s correctness rules and the type-check Run npm run check locally, and npm run format for the formatting part
The Vite terminal logs http proxy error for /api/... The API isn’t reachable at the proxy target. Under Compose that’s https://localhost:7233, which the API serves only with --launch-profile https. Start the API with --launch-profile https. Under Aspire, wait for appointme-api to run.
Symptom Cause Fix
Hand edits to src/api/client.ts disappear orval runs with clean: true and rewrites src/api/ on every run Change the backend contract or orval.config.ts instead
No diff in src/api/ after a contract change The change doesn’t show in the OpenAPI document Inspect src/AppointMe.Api/obj/openapi.json
npm run generate:api fails in the GenerateOpenApiDocuments build step The build runs the app’s startup in the Codegen environment, with no database, and new startup code needs real infrastructure Gate that code on CodeGenerationDetection.IsRunningGeneration()
On Windows, the build fails on locked DLLs A Debug build collides with the API that Aspire runs from bin/Debug Use npm run generate:api, which builds in Release for this reason
The client doesn’t match your latest backend change npx orval read the last build’s obj/openapi.json Run npm run generate:api, which builds first

A 403 from a handler names its reason in the ProblemDetails detail. The last three rows quote those reasons.

Symptom Cause Fix
/admin/jobs redirects you instead of showing the Hangfire dashboard You aren’t signed in, or your email isn’t in Authentication:SuperAdmins Sign in, and add your email to that list. Locally, demo@appointme.dev is listed.
/api/v1/login/demo returns 404 Demo:Enabled is false, or Demo:User is missing Set both, as appsettings.Development.json does
/api/v1/login/demo returns 502 with Demo login failed. Keycloak rejected the password grant for the demo user. The log says Keycloak demo login (ROPC) failed: with the status and body. Check that the realm user and Demo:User agree, and that the client allows direct access grants
403 Active company was not specified. No X-Company-Id header, or a background handler ran without a tenant See the multi-tenancy gotchas
403 The following permissions are required: … The user’s roles in this company don’t grant the permission Grant it in Settings → Permissions, or in the module’s default grant policy. See Permissions.
403 User is not authorized to access requested company. The user isn’t an employee of the company in the header Pick one of the user’s own companies. See the multi-tenancy gotchas.