flowable/flowable-engine · error · ActivitiException

couldn't get db schema version

Error message

couldn't get db schema version

What it means

The final fallback in dbSchemaCheckVersion(): if the caught exception during the schema check is neither a missing-tables error nor a RuntimeException, it is wrapped in this ActivitiException ('couldn't get db schema version') with the original as cause. It means the version check failed for an unexpected reason — typically connectivity or driver issues — rather than missing tables.

Solutions

  1. Inspect the wrapped cause (e.getCause()) for the real failure — usually a SQLException with connection/permission details.
  2. Verify the JDBC URL, credentials, and that the database is reachable (test with a plain SQL client from the same host).
  3. Confirm the correct JDBC driver jar is on the classpath and matches the DB server version.
  4. Grant the DB user rights to read the ACT_GE_PROPERTY table (or create the schema if it doesn't exist via databaseSchemaUpdate=true).

Example fix

// before: wrong credentials, cause hidden
<property name="jdbcUrl" value="jdbc:h2:tcp://localhost/act"/>
<property name="jdbcPassword" value="wrong"/>

// after: fix creds; check cause via logs
<property name="jdbcPassword" value="sa"/>
log.debug("schema check failed", e.getCause());
Defensive patterns

Strategy: try-catch

Validate before calling

// Verify DB connectivity before engine bootstrap
try (Connection c = DriverManager.getConnection(jdbcUrl, user, pass)) {
    if (!c.isValid(5)) throw new IllegalStateException("Cannot connect to database");
}

Try / catch

try {
    ProcessEngines.buildProcessEngine();
} catch (ActivitiException e) {
    if ("couldn't get db schema version".equals(e.getMessage()) && e.getCause() != null) {
        log.error("Schema check failed: {}", e.getCause().getMessage(), e.getCause());
    }
    throw e;
}

Prevention

When it happens

Trigger: getDbVersion() or table-presence checks throw a checked/non-runtime exception, e.g. SQLException wrapped as non-runtime, driver class issues, connection failures, or catalog/permission problems that don't match the missing-tables signature.

Common situations: Database unreachable or credentials wrong at engine bootstrap; missing/incorrect JDBC driver on the classpath; network/firewall drops; DB user lacking permission to query ACT_GE_PROPERTY.

Understand the failure class

Background: Database query failed: Internal Server Error 500s wrapping SQL, Prisma, and connection failures — what to check first — this error's family across 16 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable5-engine/src/main/java/org/activiti/engine/impl/db/DbSqlSession.java:953

            }
            if (dbSqlSessionFactory.isDbHistoryUsed() && !isHistoryTablePresent()) {
                errorMessage = addMissingComponent(errorMessage, "history");
            }

            if (errorMessage != null) {
                throw new ActivitiException("Activiti database problem: " + errorMessage);
            }

        } catch (Exception e) {
            if (isMissingTablesException(e)) {
                throw new ActivitiException(
                        "no activiti tables in db. set <property name=\"databaseSchemaUpdate\" to value=\"true\" or value=\"create-drop\" (use create-drop for testing only!) in bean processEngineConfiguration in flowable.cfg.xml for automatic schema creation",
                        e);
            } else {
                if (e instanceof RuntimeException) {
                    throw (RuntimeException) e;
                } else {
                    throw new ActivitiException("couldn't get db schema version", e);
                }
            }
        }

        LOGGER.debug("activiti db schema check successful");
    }

    protected String addMissingComponent(String missingComponents, String component) {
        if (missingComponents == null) {
            return "Tables missing for component(s) " + component;
        }
        return missingComponents + ", " + component;
    }

    protected String getDbVersion() {
        String selectSchemaVersionStatement = dbSqlSessionFactory.mapStatement("selectDbSchemaVersion");
        return (String) sqlSession.selectOne(selectSchemaVersionStatement);
    }

View on GitHub (pinned to d6d39ce1c6)