Reporting in Apache Fineract after Pentaho: Stretchy SQL reports and the runreports API

6/15/2026

Reporting in Apache Fineract after Pentaho: Stretchy SQL reports and the runreports API

You stand up Fineract, click into a report, and get this:

There is no ReportingProcessService registered in the ReportingProcessServiceProvider for this report type: Pentaho

So you go looking, and every guide, every Stack Overflow answer, every Mifos wiki page tells you the same thing: install Pentaho. Copy these JARs into Tomcat, set this environment variable, register this bean, add these Maven repos. People burn a day on it and still end up with a 403 Pentaho failed and a class-cast error they cannot decode.

Here is what almost nobody tells you: most of the reports you actually want do not need Pentaho at all. The on-screen tables, the CSV exports, the accounting summaries your controller pulls every month, those are plain SQL reports that have always been built into the core, and they run through one ordinary API endpoint. Pentaho is only for the pixel-perfect PDF and Excel layouts, and it left the core years ago for reasons that have nothing to do with whether you need it.

We run managed Fineract, so we set this up for a living. Here is what is actually going on.

What actually happened to Pentaho

Pentaho did not get deleted in some version, and it is not deprecated. It was un-bundled. Fineract's Pentaho integration came in from the old Mifos codebase carrying a license the Apache Software Foundation will not ship, so around the 1.6 release the project pulled it out of the core distribution and moved it to a separate, optional plugin. The engine still works. You just have to add it yourself, and most people do not need to.

The committers were blunt about why at the time. From the dev list in May 2022:

Because of license issues, Pentaho Reports are not anymore part of Fineract. You can get Pentaho Report Plugin distributed by Mifos Foundation from: github.com/openMF/fineract-pentaho

And again that November:

Fineract does not ship Pentaho reports or the related libraries, due to compliance issues with Apache licence. Please head over to the Mifos community who maintains distributions of Fineract that include pentaho.

So the error message is not a bug and not a missing dependency you forgot. It is the core telling you, correctly, that no Pentaho engine is registered, because the core does not ship one. The question is whether you need to register one, and usually the answer is no.

The part the docs skip: there are four kinds of report, and only one is Pentaho

Fineract has four report types, and the distinction is the whole game:

  • Table reports (the ones everyone calls "Stretchy") are defined by a SQL query stored in the database. This is the bulk of what ships: client listings, loan portfolio reports, the accounting summaries, the trial balance.
  • Chart reports are a Table report rendered as a bar or pie chart. Still SQL.
  • SMS reports are a SQL query whose rows feed a messaging campaign. Still SQL.
  • Pentaho reports are the only ones defined outside Fineract, in a .prpt layout file you build in Pentaho Report Designer. These are the formatted, printable documents.

Three of the four are pure SQL living in the core. Only the fourth needs the plugin. When you hit that "no ReportingProcessService registered ... for report type: Pentaho" error, you are looking at a Pentaho-type report specifically, and the fix is very often not "install Pentaho" but "you wanted the Table version of this report, which runs fine as-is."

How runreports actually works

There is one endpoint that runs all of them:

GET /fineract-provider/api/v1/runreports/{reportName}

The {reportName} is the report's human name, URL-encoded, Client Listing, Active Loans - Details, and so on. You pass the report's inputs as query parameters with an R_ prefix: R_officeId, R_loanOfficerId, R_fromDate, R_toDate, R_currencyId. A -1 usually means "all" (every loan officer, every office). The server checks you have the read permission for that specific report, looks up its type, and then forks:

  • For a Table or Chart report, it runs the stored SQL and hands you the rows. Add nothing and you get JSON, column headers plus data, which is exactly what the web app renders on screen. Add exportCSV=true and you get a CSV file instead.
  • For a Pentaho report, it hands off to the registered Pentaho engine and honours output-type, which can be HTML, PDF, XLS, or CSV.

That is the split that matters in one line: JSON and CSV come out of the built-in SQL path; PDF and XLS come out of Pentaho. If all you need is data on a screen or a spreadsheet your finance team can open, you never touch the plugin. There is even a helper, runreports/availableExports/{reportName}, that tells you which output formats a given report supports.

So the report that fails with the Pentaho error, run as a Table report with exportCSV=true, gives your accountant the same numbers in Excel without a single JAR.

A diagram of the runreports endpoint. At the top, GET /v1/runreports/{reportName} forks down into two columns. The left green column, labelled built in, no plugin: Table, Chart and SMS reports run SQL in the core (stretchy_report) and return JSON on screen or CSV with exportCSV=true. The right amber column, labelled plugin you add yourself: a Pentaho report uses a .prpt file plus the openMF/fineract-pentaho plugin to produce PDF, XLS or HTML via output-type. A note off the Pentaho box explains that the no ReportingProcessService registered for report type Pentaho error comes only from that lane.
One report endpoint, two paths. Three of the four report types are built-in SQL that needs no plugin; only Pentaho does.

Writing your own report

Because Table reports are just SQL, adding one is easy, and this is where Fineract is better than its reputation. There are three small tables behind the feature: stretchy_report holds the report and its query, stretchy_parameter holds reusable parameter definitions, and stretchy_report_parameter links the two. You do not edit those by hand in practice, there is an admin screen, System then Manage Reports then Create Report, where you give the report a name, pick the type, paste the SQL, and attach parameters.

The parameters are the nice part. Your SQL uses ${officeId} style placeholders, and they are filled from the matching R_officeId you pass at run time. The standard ones, date range, office, loan officer, currency, are backed by little "select list" parameters, which are themselves tiny reports returning id and name pairs to populate the dropdowns. So a report that takes an office filter automatically gets an office picker in the UI, wired up for you. You write a SELECT, declare which standard parameters it takes, and you have a new operational report with a real form in front of it.

One boundary worth knowing: the reports that ship with Fineract are marked as core. You can read and tweak their metadata but not delete them; the ones you create, you fully own and can edit or remove. So you build alongside the defaults, you do not fight them.

The security you cannot wave away

Here is the part I will not soften, because it is the one that gets people hurt. A Table report is raw SQL that you author and store, and it runs against your live database with Fineract's own credentials. That is powerful and it is exactly as dangerous as it sounds.

Fineract has a real SQL-injection history in this corner. Two CVEs in 2024, CVE-2024-23538 and CVE-2024-23539, were injection flaws in a report search parameter, rated up to critical, and fixed in 1.8.5 and 1.9.0. The platform has been tightening the runreports parameter handling steadily, moving toward typed validation and prepared statements, and that work is still in flight today, not finished. Which means two things for you:

  • Stay current. The report endpoint is one of the more actively patched surfaces in the codebase. Running an old version here is not a neutral choice.
  • Treat report authors like near-DBAs. Anyone who can create or edit a report can run arbitrary SQL as the application. Lock the report-authoring permission down to the few people who should have it, parameterize everything, and never let an R_ value land in your SQL unsanitised.

If you want the deeper version of this argument, it is the same logic as the rest of our security-hardening checklist for self-hosted Fineract: the engine gives you the power, the guard rails are yours to install.

The gotchas that will actually bite you

A few sharp edges, most of them real and open in the tracker:

  • Stretchy reports and PostgreSQL do not always get along. There is a long-standing open issue where some Table reports fail on Postgres that work on MySQL, usually down to SQL the report author wrote in MySQL dialect. If you are on Postgres, or moving to it, test your custom reports specifically, the engine does not translate report SQL for you.
  • A BOOLEAN parameter can break runreports on MariaDB. Another open ticket. Edge case, but a confusing one when you hit it.
  • Reports are heavy on the database and hold connections while they run. A fat report over a big portfolio is a long-running query competing with everything else. Point reporting at a read replica rather than your primary, and mind your connection pool, the same production topology advice applies here as everywhere else. A runaway report should not be able to starve loan disbursement of database connections.

When Pentaho is the right tool

None of this is "never use Pentaho." If you need a branded, paginated PDF statement, or a formatted Excel workbook with a real layout, that is exactly what Pentaho is for, and SQL reports will not get you there. The path is the Mifos-maintained plugin: you build the .prpt in Pentaho Report Designer, drop the plugin and its libraries into your deployment, point an environment variable at your reports directory, and the same runreports endpoint starts honouring output-type=PDF. It works; it is just more moving parts and a license you opt into yourself.

There is no official, license-clean replacement engine on the way: a proposal to add a BIRT-based reporting module was declined, and the only forward motion is early, experimental work to bridge Fineract's data out to external BI tools. For today the honest map is: built-in SQL reports for data and spreadsheets, the Pentaho plugin when you truly need formatted documents.

So, what should you do?

Start by assuming you do not need Pentaho. Most operational reporting, the tables your branch staff read, the CSV your finance team reconciles, the accounting summaries, is built-in SQL through the runreports API, and you can add your own report with nothing more than a SELECT and the Manage Reports screen. Reach for Pentaho only when the deliverable is a formatted document, and when you do, accept that you are taking on the plugin and its upkeep.

That upkeep is the recurring theme. Reporting in Fineract is capable, but it is one more surface to secure, patch, and keep off your primary database. Finecko runs managed Apache Fineract with the reporting set up the way it should be, the right reports against a read replica, the SQL hardened, the report permissions tight, and the version current so the next injection fix lands before you read about it. If you would rather own all of that yourself, the map above is the one the existing docs never quite draw: one endpoint, four report types, and only one of them was ever Pentaho.

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.