First-Run Troubleshooting Guide
This guide covers the most common problems new users encounter when setting up and running Wanaku for the first time. Issues are grouped by category and ranked by how likely you are to hit them.
For operational troubleshooting (authentication errors, tool invocation failures, performance tuning), see the Troubleshooting section in the Usage Guide.
Authentication and Keycloak
Router rejects all requests when Keycloak is unreachable
Symptoms:
- Router starts but management, admin, and MCP endpoints return HTTP 401
- Health check at
/q/health/readyreports OIDC as DOWN
Why this happens:
Authentication is enabled by default (wanaku.http.auth=keycloak in application.properties). If Keycloak is not running or unreachable at the configured auth.server URL, the router starts but cannot validate tokens, so all authenticated endpoints reject requests.
Fix:
Either start Keycloak first, or disable authentication entirely:
# Option 1: Use the noauth docker-compose
docker-compose -f deploy/docker-compose/docker-compose-noauth.yml up
# Option 2: Set environment variable
export WANAKU_HTTP_AUTH=none
# Option 3: Set system property
java -Dwanaku.http.auth=none -jar wanaku-barn-backend-runner.jarNo human user account exists in Keycloak
Symptoms:
- Keycloak login page appears but you have no username/password
- Admin UI and CLI authentication fail
Why this happens:
The realm import (deploy/auth/wanaku-config.json) creates the realm structure and a service account, but no human user. However, self-registration is enabled in the realm configuration.
Fix:
Either register a new account or create one manually:
- Self-register: Navigate to the Keycloak login page and click "Register" to create a new account
- Manual creation: Go to the Keycloak admin console at
http://localhost:8543/admin(login:admin/admin), select thewanakurealm, navigate to Users, and create a new user with a password
Downstream MCP servers fail to authenticate to the router
Symptoms:
- MCP server logs show repeated 401 errors during registration
- Registration retries exhaust and the service gives up silently
Why this happens:
The capabilities SDK ships with a placeholder OIDC client secret: quarkus.oidc-client.credentials.secret=<insert key here>. This is a syntactically valid but non-functional value. When authentication is enabled, downstream MCP servers need a real client secret to obtain bearer tokens for communicating with the router.
Fix:
Set the OIDC client secret as an environment variable on each downstream MCP server:
# Use the default secret from docker-compose, or your actual Keycloak secret
export QUARKUS_OIDC_CLIENT_CREDENTIALS_SECRET=mypasswdFor unauthenticated mode, set WANAKU_HTTP_AUTH=none on both the router and all downstream MCP servers.
CLI commands return 401 Unauthorized
Symptoms:
- All
wanakuCLI commands fail with authentication errors - No clear indication that login is required
Why this happens:
When the router has authentication enabled, the CLI requires an active session. The CLI does not prompt for login automatically.
Fix:
# Log in first (through the router OIDC proxy)
wanaku auth login \
--auth-server http://localhost:8080 \
--username alice \
--password
# Or log in directly against Keycloak (bypasses the router)
wanaku auth login \
--auth-server http://keycloak-host \
--realm wanaku \
--username alice \
--password
# For routers running without authentication, use --no-auth
wanaku tools list --no-authCLI commands fail with: An error occurred: Failed to communicate with Keycloak
Symptoms:
wanakuCLI commands fail to communicate with Keycloak
Example:
An error occurred: Failed to communicate with Keycloak at https://127.0.0.1:8543
Run with --verbose flag for more detailsIf you set --verbose and then shows the cause as:
sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested targetWhy this happens:
The security code (JSSE) in wanaku-cli doesn't recognize the certificate that serves the Keycloak HTTPS endpoint.
Fix:
You have two options:
You can skip the certificate checks in wanaku-cli by using the
--insecureparameter. In this case, it will show a warningWARNING: TLS certificate verification is disabled. This is insecure and should only be used for development..You can use the CA that signed the Keycloak HTTPS endpoint, by either importing it into the default Java truststore
$JAVA_HOME/lib/security/cacertsor have a particular keystore file and use the-Djavax.net.ssl.trustStoreand-Djavax.net.ssl.trustStorePasswordparameters to refer to this custom truststore.
NOTE: You can set these -D to the wanaku-cli as in this example:
java "-Djavax.net.ssl.trustStore=my-truststore.p12" "-Djavax.net.ssl.trustStorePassword=changeit" -jar quarkus-run.jar admin credentials show --admin-username=admin --admin-password=admin --keycloak-url=https://keycloak.192.168.49.2.nip.io --show-secret --client-id wanaku-serviceToken issuer mismatch causes 401 on OpenShift / Kubernetes
Symptoms:
- External clients obtain tokens from Keycloak and send them to the router
- The router rejects all tokens with HTTP 401
- Keycloak and the router are both running, and the realm is configured correctly
Why this happens:
When Keycloak is accessed via an external route (e.g. http://keycloak-wanaku-test.<cluster>/realms/wanaku), tokens are stamped with that route URL as the issuer. The router, however, validates tokens against the internal service URL (http://keycloak:8080/realms/wanaku). Because the issuers don't match, every token is rejected.
Fix:
Set KC_HOSTNAME on the Keycloak deployment to match the external route or ingress host. This forces Keycloak to stamp the same issuer in all tokens regardless of how it is accessed:
# OpenShift
KEYCLOAK_HOST=$(oc get route keycloak -n "${WANAKU_NAMESPACE}" -o jsonpath='{.spec.host}')
oc set env deployment/keycloak \
KC_HOSTNAME="${KEYCLOAK_HOST}" \
-n "${WANAKU_NAMESPACE}"
# Kubernetes (use the Ingress host instead)
KEYCLOAK_HOST=$(kubectl get ingress keycloak -n "${WANAKU_NAMESPACE}" -o jsonpath='{.spec.rules[0].host}')
kubectl set env deployment/keycloak \
KC_HOSTNAME="${KEYCLOAK_HOST}" \
-n "${WANAKU_NAMESPACE}"The deploy/auth/keycloak.yaml manifest includes a KEYCLOAK_HOST placeholder for KC_HOSTNAME — replace it with your actual hostname before applying. See also the Keycloak setup test plan for the full automated procedure.
Browser shows "502 Bad Gateway" after sign in from Keycloak
Symptoms:
When you access Wanaku web console with authentication enabled, it redirects to Keycloak for authentication, then after you input the username and password, it redirects back to Wanaku with the 502 Bad Gateway error in the browser page. If you are using nginx as loadbalancer you can verify if it logs this message upstream sent too big header while reading response header from upstream.
kubectl -n ingress-nginx logs deploy/ingress-nginx-controller|grep upstreamWhy this happens:
Nginx proxy-buffer-size defaults to 4k or 8k, so you have to increase it.
Fix:
You have to change the nginx configuration to a larger buffer size. There is this patch command to change the configuration value. In this example it increases the value to 16k.
kubectl -n ingress-nginx patch cm/ingress-nginx-controller --type=merge -p '{"data": {"proxy-buffer-size": "16k"}}'MCP Server Registration
Downstream MCP servers start but don't appear in the router
Symptoms:
- MCP server starts successfully and passes health checks
- The admin UI shows no registered services
- Service logs show warnings like
Unable to register service because of: Connection refused
Why this happens:
The registration URI defaults to http://localhost:8080 via the @WithDefault annotation in WanakuServiceConfig. This works when the router runs on the same host, but fails in Docker, Kubernetes, or multi-host setups. After 12 failed retries (approximately 60 seconds), the service gives up permanently with no re-registration mechanism.
Fix:
Set the registration URI to the router's actual address:
export WANAKU_SERVICE_REGISTRATION_URI=http://<router-host>:8080/Ensure the router is started and healthy before starting downstream MCP servers. In Docker Compose, use depends_on with condition: service_healthy.
MCP server registers but router cannot call it back
Symptoms:
- Capability appears in the admin UI
- Tool invocations fail with connection timeouts
- Router logs show connection errors to an unexpected IP address
Why this happens:
The announce-address configuration defaults to auto, which picks the first non-loopback network interface. In Docker, this is often an internal bridge IP. In multi-NIC environments, it may select a VPN tunnel interface.
Fix:
Explicitly set the announce address to an IP the router can reach:
# In the MCP server's application.properties
wanaku.service.registration.announce-address=<reachable-ip>Docker Compose and Deployment
Docker Compose does not work on macOS with Podman
Symptoms:
- Services fail to start or cannot communicate with each other
Why this happens:
All services in the provided docker-compose.yml use network_mode: host, which is not supported on macOS with Podman (see podman#15664).
Fix:
Use Docker Desktop on macOS instead of Podman, or modify the compose file to use bridge networking with explicit port mappings.
Router health check is silently ignored in docker-compose.yml
Symptoms:
- MCP servers start before the router is ready
- Registration fails due to race conditions
- Startup succeeds on retry but is unreliable
Why this happens:
In deploy/docker-compose/docker-compose.yml, the healthcheck: block for the router is at the wrong YAML indentation level. It appears as a top-level key rather than nested under the wanaku-router service, so Docker Compose ignores it entirely.
Fix:
If you experience startup race conditions, add a delay before starting MCP servers, or fix the indentation in your local copy of the compose file so the healthcheck is nested under the wanaku-router service definition.
Insecure default credentials in docker-compose
Symptoms:
No error, which is the problem. The provided docker-compose ships with well-known credentials.
Why this happens:
The development docker-compose uses default credentials for convenience:
- Keycloak admin:
admin/admin - OIDC client secret for
wanaku-service:mypasswd
Fix:
Before any non-local deployment, rotate these credentials:
- Change
KEYCLOAK_ADMIN_PASSWORDin the compose file - Update the
wanaku-serviceclient secret in Keycloak - Update
QUARKUS_OIDC_CLIENT_CREDENTIALS_SECRETon all downstream MCP servers to match
SDK and MCP Server Development
Port 8080 conflict between router and new MCP servers
Symptoms:
java.net.BindException: Address already in usewhen starting an MCP server alongside the router
Why this happens:
MCP servers often default to port 8080, which is the same as the router.
Fix:
Set a non-conflicting port in the MCP server's application.properties:
# Use a specific port
quarkus.http.port=9090
# Or let Quarkus pick a random available port
quarkus.http.port=0Frontend and Admin UI
CORS errors when frontend runs on a non-default port
Symptoms:
- Browser console shows CORS preflight failures
- API calls from the frontend are blocked
Why this happens:
The router's CORS allowlist is configured for specific origins: localhost:8080, 127.0.0.1:8080, localhost:5173, and localhost:6274. If Vite's dev server runs on a different port (which happens automatically when 5173 is already in use), requests are blocked.
Fix:
Add your dev server's origin to the router's configuration:
# In apps/wanaku-barn-backend/src/main/resources/application.properties
quarkus.http.cors.origins=http://localhost:8080,http://127.0.0.1:8080,http://localhost:5173,http://localhost:6274,http://localhost:<your-port>Performance
Opaque "Generic error" responses
Symptoms:
- API responses contain only
{"error": "Generic error"}with HTTP 500 - No indication of what went wrong
Why this happens:
The router's BaseExceptionMapper catches all unhandled exceptions and returns a sanitized error message. The actual exception details are logged server-side but not exposed in the API response.
Fix:
Check the router's server logs for the real stack trace:
- Dev mode:
target/logs/wanaku.log - Docker:
docker logs <container-name> - Kubernetes:
kubectl logs <pod-name>
Enable debug logging for more detail:
quarkus.log.category."ai.wanaku".level=DEBUGSystem-Level Issues
Module access errors on Java 25
Symptoms:
wanaku --versionor anywanakucommand fails immediately withIllegalAccessError,InaccessibleObjectException, or a stack trace mentioningjava.base/java.langmodule access- Running with
JAVA_TOOL_OPTIONS='--add-opens=java.base/java.lang=ALL-UNNAMED'resolves the error
Why this happens:
Java 25 tightened strong encapsulation of internal JDK classes. Some dependencies used by Quarkus and the CLI attempt reflective access to java.lang internals that are no longer automatically open.
Fix:
The Wanaku CLI and router scripts already pass --add-opens=java.base/java.lang=ALL-UNNAMED by default on Java 25. If you run the JAR directly (e.g., java -jar quarkus-run.jar), add the option manually:
java --add-opens=java.base/java.lang=ALL-UNNAMED -jar quarkus-run.jar --versionIf you still encounter module access errors for other packages, add the corresponding --add-opens or --add-exports flag. Report the full stack trace as a new issue so we can extend the launcher defaults.
Infinispan data directory permissions in containers
Symptoms:
- Router fails at startup with file permission errors
- Persistence data is silently lost between restarts
Why this happens:
The Infinispan data directory defaults to ${wanaku.home}/router/. In container images, this resolves to /home/jboss/.wanaku/router/. Running the container with a different UID or mounting a host directory with incompatible permissions causes Infinispan's SoftIndexFileStore to fail.
Fix:
Use named Docker volumes (which handle permissions automatically) rather than host-mounted directories. If you must use host mounts, ensure the directory is owned by UID 185 (the jboss user in the container image).
Multiple router replicas have independent state
Symptoms:
- Changes made on one router instance (tool registrations, resource additions) are not visible on other instances
- Inconsistent behavior depending on which replica handles the request
Why this happens:
Infinispan is configured in LOCAL cache mode. Each router instance maintains its own isolated data store. There is no replication or synchronization between instances.
Fix:
Currently, Wanaku supports single-instance deployments only. Running multiple replicas requires architectural changes to enable distributed Infinispan cache modes. For high availability, use a single replica with persistent storage.
Crashed MCP servers are not detected for up to 60 seconds
Symptoms:
- An MCP server crashes but tool calls to it continue failing for about a minute before the router marks it as unhealthy
Why this happens:
The router's periodic health check runs every 60 seconds (wanaku.router.health-check.interval-seconds=60). Between checks, the router assumes previously registered MCP servers are still healthy.
Fix:
Reduce the health check interval for faster detection (at the cost of increased network traffic):
wanaku.router.health-check.interval-seconds=15Getting Help
If your issue is not covered here:
- Check the operational troubleshooting section in the Usage Guide
- Review the FAQ for common questions
- Search GitHub Issues for similar problems
- Open a new issue with your Wanaku version, deployment environment, steps to reproduce, and relevant log excerpts