Skip to content

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/v1

Common mistakes:

  • Using http:// instead of https://
  • Using port 8080 (only valid if TLS is explicitly disabled)
  • Missing the /fineract-provider/api/v1 path 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:

  1. Pass -k / --insecure with curl (local testing only)
  2. Import the self-signed cert into your truststore
  3. 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: default

Without 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:

DatabasePurpose
fineract_tenantsRegistry of all tenants and their connection details
fineract_defaultThe 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.

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_PASSWORD

The JDBC URL format for MySQL/MariaDB:

jdbc:mariadb://<host>:<port>/fineract_tenants

For PostgreSQL:

jdbc:postgresql://<host>:<port>/fineract_tenants

Liquibase 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, and REFERENCES privileges
  • Stale lock from a crashed previous run - Liquibase leaves a lock in the DATABASECHANGELOGLOCK table. Clear it with:
    sql
    UPDATE 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 - clientId not ClientId
  • Numeric fields sent as strings (or vice versa) - "principal": 10000 not "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

  1. Verify COB is enabled: FINERACT_JOB_LOAN_COB_ENABLED=true (default)
  2. Check batch manager is active: FINERACT_MODE_BATCH_MANAGER_ENABLED=true (default)
  3. Check the job schedule: The COB job must have a cron trigger configured. Query the scheduler API to verify:
    bash
    GET /fineract-provider/api/v1/jobs
    Look for Loan COB and confirm currentlyRunning: false and a valid nextRunTime.
  4. Remote job messaging must be configured correctly - exactly one of FINERACT_REMOTE_JOB_MESSAGE_HANDLER_SPRING_EVENTS_ENABLED, _JMS_ENABLED, or _KAFKA_ENABLED must be true. 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/inline

Inline 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-TenantId header must match the identifier column in fineract_tenants.tenants exactly (case-sensitive)
  • If using the Finecko Hub API to create tenants, use the id returned 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

TipDetail
Read the full exception chainThe root cause is always the last Caused by: entry in a stack trace
Enable DEBUG loggingSet logging.level.org.apache.fineract=DEBUG to get detailed request/response logs
Check Actuator healthGET /actuator/health shows DB connectivity, disk space, and other indicators
Verify all required headersEvery request needs Fineract-Platform-TenantId and Authorization
Use Swagger UIThe built-in Swagger UI at /fineract-provider/api/v1/swagger-ui/index.html shows exact required fields per endpoint
Check job run historyGET /fineract-provider/api/v1/jobs/{jobId}/runhistory shows recent job outcomes with error messages