Why your Apache Fineract instance won't start (and the errors everyone hits)

6/13/2026

Why your Apache Fineract instance won't start (and the errors everyone hits)

Apache Fineract is a backend you assemble, not an app you install, and a fresh instance has a small, predictable set of ways to not start. We run managed Fineract for a living, and we answer the same handful of "it won't start" questions on the mailing list constantly, so here is the consolidated, current version: the errors a new instance throws, why, and the fix for each.

Two things up front. First, most "won't start" reports are configuration, not bugs. Second, the symptoms arrive in a confusing order, and the error at the top of the stack trace is rarely the real one. The whole game is knowing which of these you are looking at. They group into three buckets: it boots but every request fails, it does not boot at all, and it is actually fine but looks broken.

A troubleshooting decision tree. Instance will not start: does it boot? No leads to the boot failures (Java 21, the two databases, the DB connection, a stuck Liquibase lock, the JDBC driver). Yes leads to: does every request fail? Yes leads to the request failures (the wrong path giving a 404, the missing tenant header giving a 400, TLS). No means it is running, so set the timezone before go-live.
Where to start when it will not start: is it a boot failure, a request failure, or actually running?

It boots but every request fails

This is the most common cluster, and the most confusing, because the server says it is up while every call bounces.

404 on everything. Fineract is not served from the root. The API lives at /fineract-provider/api/v1, over HTTPS on port 8443, and health is at /fineract-provider/actuator/health. Hitting https://localhost:8443/ or /api gives you a 404 or a Spring whitelabel page. A common sub-trap is doubling the version, /api/v1/v1/..., when your client already adds it. Confirm the server is up with the health endpoint, then point everything at the full path.

400 Bad Request on every call. Fineract is multi-tenant, so every request has to say which tenant it is for. Leave that out and you get a 400, even when everything else is correct. Send the header Fineract-Platform-TenantId: default (or ?tenantIdentifier=default) on every request.

"This combination of host and port requires TLS." SSL is on by default (FINERACT_SERVER_SSL_ENABLED=true), and the instance ships a self-signed development certificate that browsers and HTTP clients reject. Use https, and either accept the certificate once in the browser, pass -k to curl, or import the cert into your client's trust store. For local development only, you can set FINERACT_SERVER_SSL_ENABLED=false and talk plain HTTP on 8080.

It does not boot at all

The wrong Java version. This is the single biggest source of stale instructions online. Current Fineract requires Java 21. It has moved from 8 to 11 to 17 to 21 over the years, so most guides you will find are wrong. If the build fails with an "unsupported class file" error, or a WAR deploys but never initializes, check your JDK first.

The two databases are not there. Fineract needs two stores, not one: a tenant registry (fineract_tenants) that lists your tenants and how to reach them, and at least one tenant data store (fineract_default) that holds the actual clients and loans. On PostgreSQL these are two databases; on MySQL or MariaDB, two schemas. Miss one and startup dies with something like database "fineract_tenants" does not exist. Create both before you boot.

The database is there but the connection is refused. Wrong host, wrong port, wrong credentials, or the database simply is not up yet. The trap is the stack trace: the first exceptions are generic Spring and Hikari noise, and the real cause is at the very bottom, where you will find the actual Connection refused or Access denied. Read the last exception, not the first, then fix the FINERACT_DEFAULT_TENANTDB_* and FINERACT_HIKARI_* values to match your database.

The Liquibase lock is stuck. Fineract runs its database migrations with Liquibase on startup. If a previous start died mid-migration, the lock row in the DATABASECHANGELOGLOCK table stays held, and the next start hangs or fails with Could not acquire change log lock. Clear it with UPDATE DATABASECHANGELOGLOCK SET locked=0 WHERE id=1; and start again. This gets worse with multiple replicas: several instances try to migrate at once and race for the lock. The fix is to stop relying on migrate-on-startup and run migrations as a single separate step before you deploy the app instances, which we covered in the production guide.

The JDBC driver and your database engine. PostgreSQL is the first-class, recommended engine now, and the path of least resistance. If you are on MySQL or MariaDB, note that recent Apache releases remove those JDBC drivers from the distribution for licensing reasons, so you supply the driver yourself and set the driver class (FINERACT_HIKARI_DRIVER_SOURCE_CLASS_NAME) and a matching jdbc: URL. A driver that does not match the URL scheme throws at boot during pool initialisation.

It is actually fine, it just looks broken

bootRun sits at 98 percent. Running from source, ./gradlew bootRun shows "Executing 98%" and seems to hang forever. It is not hung. bootRun is a long-running task, so Gradle parks at 98 percent while the application runs. Look in the log for Started ServerApplication or Tomcat started on port, and it is up.

There is no UI at the root. Fineract is a headless backend; it has no bundled web interface, so a 404 at the root is expected, not a failure. The web UI is a separate application (the Mifos web app) that you run on its own and point at the Fineract API.

The timezone trap

This one does not stop startup, which is exactly why it is dangerous: it bites in production a few days later. The default tenant timezone is Asia/Kolkata. If you leave it on the default, your business date, your Close of Business run, and every scheduled job operate against the wrong day. Set FINERACT_DEFAULT_TENANTDB_TIMEZONE to your institution's timezone before go-live. (The business-date mechanics are in the Close of Business post.)

And the credentials

The default application login is mifos / password on tenant default, and these are separate from your database credentials. People change the database password, then cannot log in to the app, because the two are unrelated. Log in with the app defaults, and change them immediately.

If you are building from source

Most of the above is about running a built instance. If you are compiling Fineract yourself, a few extra things bite:

  • Use Java 21 and a clean build. Incremental Gradle builds can fail oddly (the Avro code generation does not always play nicely with the build cache). If you hit a strange "failed to read candidate component class" error, build with ./gradlew --no-daemon --no-build-cache build.
  • "Found N files with unapproved licenses." This is the Apache license-header check (RAT) failing on stray or generated files in your working tree, not a Fineract bug. Clean the offending files. It is a build-from-source stumble, not something a deployed instance ever sees.
  • The EclipseLink "ClassTransformer" warning is harmless. You may see an alarming line about failing to register a ClassTransformer, or pages of static-weaving log output. On a modern run it is noise, not the reason your build failed. Look elsewhere.
  • Skip the tests for a quick local boot with -x test. The end-to-end suite is heavy and occasionally red on the development branch, and it is not what you need to just bring the server up.

So, what should you do?

None of these is hard once you know which one you are staring at. Each is a five-minute fix, and our docs have the deep configuration: the troubleshooting guide, the local development guide, and the full environment variables reference. The hard part is that a fresh Fineract hands you the symptoms in the wrong order, on your first afternoon with it, when you have the least context to tell them apart.

That is the part we take off your plate. Finecko runs managed Apache Fineract, so the instance is already up, on the right Java, the right database, the right timezone, behind a real certificate, with migrations handled, and none of the above is your problem. If you would rather run it yourself, work down this list when it will not start, read the bottom of the stack trace, and you will clear almost everything a fresh instance throws at you.

Skip the ops. Run managed Apache Fineract.

Finecko runs managed Apache Fineract for you - the Finecko Hub, the right topology, connection pooling, backups, TLS, patching, and on-call. You get the open-source core without the operations, and the free plan is a full environment to try with no credit card.