Appearance
Troubleshooting & Common Issues
This page covers the most common errors and misconfigurations you will encounter when working with Apache Fineract. Issues are grouped by category.
Root cause first
When Fineract throws an exception, the first exception in the log is rarely the real problem. Scroll to the end of the exception chain - the root cause is almost always the last Caused by: entry.
Connection & Endpoint Issues
"Connection refused" on port 8080 or 8443
Fineract listens on port 8443 over HTTPS by default (TLS enabled). Connecting over plain HTTP or to the wrong port will result in a connection refused or TLS handshake error.
Default base URL:
https://<host>:8443/fineract-provider/api/v1Common mistakes:
- Using
http://instead ofhttps:// - Using port
8080(only valid if TLS is explicitly disabled) - Missing the
/fineract-provider/api/v1path segment entirely
"SSL certificate problem: self-signed certificate"
Fineract ships with a self-signed certificate by default. When testing locally this is expected behaviour.
Options:
- Pass
-k/--insecurewithcurl(local testing only) - Import the self-signed cert into your truststore
- Replace with a valid certificate signed by a trusted CA (recommended for production)
On Finecko: All endpoints are served over TLS with a valid certificate. No self-signed cert issues should occur.
Authentication & Header Issues
HTTP 400 on every request
The most common cause is a missing or incorrect tenant identifier. Fineract is multi-tenant and requires a tenant header on every request.
http
Fineract-Platform-TenantId: defaultWithout this header (or with an unrecognised tenant ID) Fineract returns a 400 with a message similar to:
json
{
"developerMessage": "The requested tenant identifier could not be found: null"
}Fix: Add the Fineract-Platform-TenantId header to every request. The value must match a tenant registered in the fineract_tenants database. For a fresh installation the default tenant is default.
HTTP 401 Unauthorized
Basic authentication is required for all endpoints except the public /authentication endpoint.
- Credentials are sent as a Base64-encoded
Authorization: Basic <base64(user:password)>header - Default credentials on a fresh installation:
mifos/password - After the first login, change the default password immediately via the Users API
Alternatively, authenticate via the /authentication endpoint and use the returned token:
bash
curl -X POST https://<host>:8443/fineract-provider/api/v1/authentication \
-H "Fineract-Platform-TenantId: default" \
-H "Content-Type: application/json" \
-d '{"username":"mifos","password":"password"}'The response contains a base64EncodedAuthenticationKey that can be used as a Bearer token or directly as the Basic auth value.
HTTP 403 Forbidden
The authenticated user exists but lacks the required permission for the requested operation.
- Check the user's assigned roles and the permissions attached to those roles
- The error response body includes the specific permission code that was missing, for example
APPROVE_LOAN - Assign the user a role that includes the required permission, or create a custom role
Database Issues
"Table 'fineract_tenants.tenants' doesn't exist" or "Unknown database 'fineract_tenants'"
Fineract requires two databases to be present before startup:
| Database | Purpose |
|---|---|
fineract_tenants | Registry of all tenants and their connection details |
fineract_default | The actual data store for the default tenant |
If either is missing, Fineract will fail on startup with a Liquibase or connection error.
Fix: Create both databases before starting Fineract:
sql
CREATE DATABASE fineract_tenants;
CREATE DATABASE fineract_default;Then ensure the FINERACT_HIKARI_* connection variables point at the correct host and credentials.
"Communications link failure" or "Connection to <host>:3306 refused"
The database host or port in your configuration does not match the actual database location.
Check these environment variables:
FINERACT_HIKARI_DRIVER_SOURCE_CLASS_NAME
FINERACT_HIKARI_JDBC_URL
FINERACT_HIKARI_USERNAME
FINERACT_HIKARI_PASSWORDThe JDBC URL format for MySQL/MariaDB:
jdbc:mariadb://<host>:<port>/fineract_tenantsFor PostgreSQL:
jdbc:postgresql://<host>:<port>/fineract_tenantsLiquibase migration fails on startup
Fineract runs Liquibase migrations automatically on startup for each tenant. Migration failures are usually caused by:
- Insufficient DB user permissions - the DB user needs
CREATE,ALTER,INDEX,DROP, andREFERENCESprivileges - Stale lock from a crashed previous run - Liquibase leaves a lock in the
DATABASECHANGELOGLOCKtable. Clear it with:sqlUPDATE DATABASECHANGELOGLOCK SET LOCKED=0, LOCKGRANTED=NULL, LOCKEDBY=NULL WHERE ID=1; - Schema version mismatch - if downgrading Fineract versions, the schema may be ahead of what the older version expects. Fineract does not support downgrade migrations.
API Request Issues
Date fields return a 400 or validation error
Fineract requires dateFormat and locale alongside any date field in a request body:
json
{
"expectedDisbursementDate": "01 March 2025",
"dateFormat": "dd MMMM yyyy",
"locale": "en"
}Without dateFormat and locale, date fields cannot be parsed and Fineract returns a 400.
"Required field missing" even though the field is present
Check for:
- JSON field names are case-sensitive -
clientIdnotClientId - Numeric fields sent as strings (or vice versa) -
"principal": 10000not"principal": "10000" - Nested objects required but sent as primitives
The 400 error response includes a field-level errors array:
json
{
"errors": [
{
"parameterName": "principal",
"developerMessage": "The parameter principal cannot be blank."
}
]
}Read each entry in errors - do not just look at the top-level message.
COB (Close of Business) Issues
COB never runs / business date does not advance
- Verify COB is enabled:
FINERACT_JOB_LOAN_COB_ENABLED=true(default) - Check batch manager is active:
FINERACT_MODE_BATCH_MANAGER_ENABLED=true(default) - Check the job schedule: The COB job must have a cron trigger configured. Query the scheduler API to verify:bashLook for
GET /fineract-provider/api/v1/jobsLoan COBand confirmcurrentlyRunning: falseand a validnextRunTime. - Remote job messaging must be configured correctly - exactly one of
FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED,_JMS_ENABLED, or_KAFKA_ENABLEDmust betrue. If more than one is enabled, COB will fail to dispatch partitions.
COB is stuck / loans are locked
If COB is interrupted mid-run, loans in the current partition may remain locked. Locked loans are tracked in the m_loan_cob_error table.
Check for stuck loans:
sql
SELECT COUNT(*) FROM m_loan WHERE loan_sub_status_enum = 700;To unlock (after confirming COB is not actively running):
bash
PUT /fineract-provider/api/v1/jobs/Loan COB/inlineInline execution restarts and completes any locked loans.
Business date is behind by more than one day
If COB has been failing silently for several days, the business date will fall behind real time. After fixing the underlying issue, COB will need to run once per missed day to catch up. Business date advancement is a single-day increment per COB run.
See the COB technical guide for full recovery steps.
Multi-Tenancy Issues
Tenant exists in fineract_tenants but requests return "tenant not found"
- The value in the
Fineract-Platform-TenantIdheader must match theidentifiercolumn infineract_tenants.tenantsexactly (case-sensitive) - If using the Finecko Hub API to create tenants, use the
idreturned by the Hub as the tenant identifier
New tenant's database migrations fail on creation
When a new tenant is provisioned, Fineract runs Liquibase against the new tenant's database. Failures here mean the DB user does not have sufficient privileges on the newly created database, or the database itself was not created before Fineract attempted to connect.
On Finecko: Tenant provisioning is handled asynchronously by the Hub via a Kubernetes Job. If provisioning fails, check the Hub API for the tenant's provisioning status.
General Debugging Tips
| Tip | Detail |
|---|---|
| Read the full exception chain | The root cause is always the last Caused by: entry in a stack trace |
| Enable DEBUG logging | Set logging.level.org.apache.fineract=DEBUG to get detailed request/response logs |
| Check Actuator health | GET /actuator/health shows DB connectivity, disk space, and other indicators |
| Verify all required headers | Every request needs Fineract-Platform-TenantId and Authorization |
| Use Swagger UI | The built-in Swagger UI at /fineract-provider/api/v1/swagger-ui/index.html shows exact required fields per endpoint |
| Check job run history | GET /fineract-provider/api/v1/jobs/{jobId}/runhistory shows recent job outcomes with error messages |