flowable/flowable-engine · error · FlowableObjectNotFoundException

Could not find a table with name

Error message

Could not find a table with name '${tableName}'.

What it means

The REST table data endpoint GET /management/tables/{tableName} verifies via managementService.getTableMetaData() that the requested database table exists before querying its rows. If the metadata lookup returns null, a FlowableObjectNotFoundException is thrown. This guards against querying arbitrary or misspelled table names.

Solutions

  1. List valid tables with GET /management/tables and use an exact name from that list.
  2. Fix the table name spelling/case to match the database schema (e.g. ACT_RU_TASK).
  3. Verify the REST app's datasource points to the database containing the flowable tables.
  4. Catch FlowableObjectNotFoundException (HTTP 404) in the client and handle missing-table gracefully.

Example fix

// before
curl http://localhost:8080/flowable-rest/management/tables/ACT_RU_TSK
// after
curl http://localhost:8080/flowable-rest/management/tables/ACT_RU_TASK
Defensive patterns

Strategy: validation

Validate before calling

const tables = await fetch('/management/tables').then(r => r.json());
if (!tables.data.some(t => t.name === tableName)) throw new Error(`Unknown table ${tableName}`);

Try / catch

try { const data = await getTableData(name); } catch (e) { if (e.status === 404) { /* table does not exist */ } else throw e; }

Prevention

When it happens

Trigger: GET /management/tables/{tableName}?start=..&size=.. where {tableName} does not match any table exposed by managementService (e.g. typo like 'ACT_RU_TSK' instead of 'ACT_RU_TASK', or a table from another schema/database).

Common situations: Typo in table name; querying a table after the flowable schema version changed (e.g. ACT_ prefix tables renamed); pointing the REST app at a different database than expected; casing mismatch on case-sensitive databases (PostgreSQL).

Understand the failure class

Background: 'Could not be found', 'does not exist', 'not found in database': the resource-not-found family when an ID, slug, key, or URI lookup comes back empty — this error's family across 20 libraries.

Related errors


AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11). Data as JSON: /api/errors/61f1615a4353df66. Report an issue: GitHub.

Appendix: source

Thrown at modules/flowable-rest/src/main/java/org/flowable/rest/service/api/management/TableDataResource.java:79

    @ApiImplicitParams({
            @ApiImplicitParam(name = "start", dataType = "integer", value = "Index of the first row to fetch. Defaults to 0.", paramType = "query"),
            @ApiImplicitParam(name = "size", dataType = "integer", value = "Number of rows to fetch, starting from start. Defaults to 10.", paramType = "query"),
            @ApiImplicitParam(name = "orderAscendingColumn", dataType = "string", value = "Name of the column to sort the resulting rows on, ascending.", paramType = "query"),
            @ApiImplicitParam(name = "orderDescendingColumn", dataType = "string", value = "Name of the column to sort the resulting rows on, descending.", paramType = "query"),
    })
    @ApiResponses(value = {
            @ApiResponse(code = 200, message = "Indicates the table exists and the table row data is returned"),
            @ApiResponse(code = 404, message = "Indicates the requested table does not exist.")
    })
    @GetMapping(value = "/management/tables/{tableName}/data", produces = "application/json")
    public DataResponse<List<Map<String, Object>>> getTableData(@ApiParam(name = "tableName") @PathVariable String tableName, @ApiParam(hidden = true) @RequestParam Map<String, String> allRequestParams) {
        if (restApiInterceptor != null) {
            restApiInterceptor.accessTableInfo();
        }
        
        // Check if table exists before continuing
        if (managementService.getTableMetaData(tableName) == null) {
            throw new FlowableObjectNotFoundException("Could not find a table with name '" + tableName + "'.", String.class);
        }

        String orderAsc = allRequestParams.get("orderAscendingColumn");
        String orderDesc = allRequestParams.get("orderDescendingColumn");

        if (orderAsc != null && orderDesc != null) {
            throw new FlowableIllegalArgumentException("Only one of 'orderAscendingColumn' or 'orderDescendingColumn' can be supplied.");
        }

        Integer start = null;
        if (allRequestParams.containsKey("start")) {
            start = Integer.valueOf(allRequestParams.get("start"));
        }

        if (start == null) {
            start = 0;
        }

View on GitHub (pinned to d6d39ce1c6)