Troubleshooting
Hazelcast connectivity
Symptoms:
-
Startup fails in cache services that treat Hazelcast as mandatory (e.g.,
TabCacheServicethrows on init failure). -
Some caches may disable themselves when Hazelcast is offline (
ColumnDefinitionCacheServicecatchesHazelcastClientOfflineExceptionand sets cache to null).
Checks:
-
Ensure Hazelcast members are reachable from the service network.
-
Verify
HZ_MEMBERSis set correctly in the deployment environment. -
Verify
hazelcast-client.cluster-namematches the cluster (devin production for this system).
Liquibase migration failures
Symptoms:
-
Application fails at startup with Liquibase errors.
Checks:
-
Inspect
db/changelog/db.changelog-master.yamlordering and the failing change set. -
Confirm DB user has DDL permissions for initial install and migrations.
502 Bad Gateway from the UI proxy
Symptoms:
-
The UI loads (login page, static assets, fonts return
200), but every API call under/configs-service/**(auth/me,csrf,auth/login,environment/snapshot) returns502 Bad Gatewayfrom nginx. -
The UI container log shows, for each proxied request:
[error] <host> could not be resolved (2: Server failure)(DNSSERVFAIL).
Cause:
-
The UI’s nginx is configured to proxy the API to a public FQDN (e.g.
BACKEND_URL=http://qa63.friendly-tech.com:8086). nginx must resolve that name before proxying, but the resolution fails inside the container, so nginx has no upstream to forward to and returns502. -
Static assets are served from local files (no DNS needed), which is why only the proxied API calls fail — the backend process itself is healthy and listening (verify with
ss -ltnp | grep 8080on the host andcurl http://localhost:8080/configs-service/actuator/health). -
A common root trigger: the public FQDN resolves to IPv6 only (an
AAAArecord, noArecord), while the Docker bridge network is IPv4-only. The container’s embedded DNS (127.0.0.11) returnsSERVFAILfor the IPv4 (A) lookup. Confirm withgetent hosts <fqdn>on the host (shows an IPv6 address) versusdocker exec <ui-container> getent hosts <fqdn>(returnsSERVFAIL).
Fixes:
-
Preferred — point the UI at the backend by its internal Compose/Kubernetes service name instead of the public FQDN, so resolution stays on the container network’s DNS and never leaves it:
BACKEND_URL=http://ft-configs-service:8080This is the cleanest fix and removes the dependency on external DNS entirely. The UI and backend must share a Docker network (same Compose project / namespace).
-
If the public FQDN must be kept, restore the missing
A(IPv4) record in DNS, or add anextra_hostsentry to the UI container mapping the FQDN to the host’s IPv4 (e.g."<fqdn>:host-gateway"). A missingArecord affects every IPv4 consumer of that name, not just this UI — fix it in DNS rather than only working around it per container.
After repointing the UI, make sure CORS_ALLOWED_ORIGINS on the backend lists the origin the browser uses — including the https:// UI origin, not only http:// (see Invalid CORS request below). The internal service name (ft-configs-service) is never a browser origin and must not be added to CORS.
|
Invalid CORS request
Symptoms:
-
API requests are blocked by the browser with
Invalid CORS request, or preflightOPTIONScalls fail, even though the backend is reachable.
Cause:
-
CORS_ALLOWED_ORIGINSdoes not contain the exact origin (scheme + host + port) shown in the browser address bar. Origins are scheme-sensitive:http://andhttps://are distinct origins. -
The UI is served on both HTTP and HTTPS (default ports
3001for HTTP and3443for HTTPS), but only thehttp://origin was allow-listed, so HTTPS page loads are blocked.
Fixes:
-
List every origin the UI is reachable on — both the
http://andhttps://variants:CORS_ALLOWED_ORIGINS=http://<ui-host>:3001,https://<ui-host>:3443 -
The value must match the browser URL exactly; do not use the internal Docker service name here.
Authentication issues
Symptoms:
-
401 responses; UI cannot stay logged in.
Checks:
-
Confirm
JWT_SECRETis Base64-encoded (decoded viaDecoders.BASE64inJwtService). -
Confirm cookies are sent (consider
cookie.secureand HTTPS termination). -
Confirm CSRF token is fetched from
GET /configs-service/csrfand sent via header expected by Spring Security.
Mail mode / deletion email
Symptoms:
-
Account deletion request fails with error code
USER_DELETION_EMAIL_REQUIRED("User email is required to request account deletion"). -
No emails are being sent (onboarding, deletion OTP), or you expected offline behavior but the service still requires email.
Causes:
-
The service is in online mode but the initiating admin has no email address (the deletion OTP is sent to that admin).
-
You expected offline mode, but
MAIL_MODE/SMTP config resolves to online. A common pitfall: underMAIL_MODE=AUTO, a profile that referenced${MAIL_PASSWORD}without an empty default left the literal placeholder${MAIL_PASSWORD}(non-blank), so AUTO wrongly inferred online. All three profiles now use empty defaults (${MAIL_USERNAME:}/${MAIL_PASSWORD:}).
A configured-but-unreachable SMTP server under MAIL_MODE=AUTO no longer fails the deletion: it degrades to the no-OTP path (request returns otpRequired=false, tokenless confirm deletes the user).
|
Fixes:
-
For air-gapped installs, set
MAIL_MODE=OFFLINE. Temporary passwords are then returned in the create-user/reset-password API responses (passwordDelivery=RETURNED) and deletion OTP is disabled (the request returnsotpRequired=falseand the account is deleted in the confirm step, called without an OTP). -
For email delivery, give the initiating admin an email address and configure real, reachable SMTP credentials (
MAIL_HOST/MAIL_USERNAME/MAIL_PASSWORD) underMAIL_MODE=AUTO. -
Check the startup log line
Mail delivery: mode=…, smtpConfigured=…, effectiveOffline=…to confirm the resolved mode.
See Configuration — Delivery modes for details.