flowable/flowable-engine · error · FlowableException
Error parsing Historic Case Instance Migration Document
Error message
Error parsing Historic Case Instance Migration Document
What it means
HistoricCaseInstanceMigrationDocumentConverter.convertFromJson parses the migration document JSON with Jackson. Any JacksonException (malformed JSON, wrong node types, invalid structure) is wrapped and rethrown as this FlowableException with the Jackson exception as cause.
Solutions
- Validate the migration document JSON with a JSON linter/parser before passing it in.
- Generate the document programmatically via HistoricCaseInstanceMigrationDocument or the builder API instead of hand-writing JSON.
- Inspect the wrapped JacksonException cause for the exact line/problem.
- Check property names against the converter's JSON constants (e.g. toCaseDefinitionKey, mappings).
Example fix
// before
String doc = "{ toCaseDefinitionKey: orderCase }"; // unquoted key -> JacksonException
// after
String doc = "{\"toCaseDefinitionKey\":\"orderCase\"}"; Defensive patterns
Strategy: validation
Validate before calling
new ObjectMapper().readTree(migrationJson); // throws JsonProcessingException before engine sees it
Type guard
try { JsonNode n = new ObjectMapper().readTree(json); return n != null && n.isObject(); } catch (JsonProcessingException e) { return false; } Try / catch
try { document = converter.convertFromJson(jsonStream); } catch (FlowableException e) { if (e.getMessage().equals("Error parsing Historic Case Instance Migration Document")) { log("Bad migration JSON", e.getCause()); } throw e; } Prevention
- Generate migration documents via the builder API instead of hand-written JSON.
- Lint all migration JSON in CI.
- Version-control and review migration documents like code.
- Always check the cause JacksonException for precise error location.
When it happens
Trigger: Calling convertFromJson (e.g. when building a migration from a JSON document string/resource) where the JSON is syntactically invalid or contains fields with unexpected types (e.g. mappings where an array or object is expected).
Common situations: Hand-edited migration JSON files; JSON generated with wrong property names so nested structures don't match; passing a non-migration JSON file; encoding/newline corruption in resources.
Understand the failure class
Background: JSON parse error: "Unexpected token" / "not valid JSON" / "failed to parse" — what JSON parsers are really complaining about — this error's family across 45 libraries.
Related errors
- Error parsing Case Instance Migration Document
- Error parsing Process Instance Migration Document
- Cannot aggregate overview variable
- Cannot aggregate variable
- Cannot find the case definition to migrate to, identified by
AI-assisted analysis of flowable/flowable-engine@d6d39ce1c6 (2026-09-11).
Data as JSON: /api/errors/f60ed483d1580382.
Report an issue: GitHub.
Appendix: source
Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/migration/HistoricCaseInstanceMigrationDocumentConverter.java:78
public static HistoricCaseInstanceMigrationDocument convertFromJson(String jsonCaseInstanceMigrationDocument) {
try {
JsonNode rootNode = objectMapper.readTree(jsonCaseInstanceMigrationDocument);
HistoricCaseInstanceMigrationDocumentBuilderImpl documentBuilder = new HistoricCaseInstanceMigrationDocumentBuilderImpl();
documentBuilder.setCaseDefinitionToMigrateTo(getJsonProperty(TO_CASE_DEFINITION_ID_JSON_PROPERTY, rootNode));
String caseDefinitionKey = getJsonProperty(TO_CASE_DEFINITION_KEY_JSON_PROPERTY, rootNode);
Integer caseDefinitionVersion = getJsonPropertyAsInteger(TO_CASE_DEFINITION_VERSION_JSON_PROPERTY, rootNode);
documentBuilder.setCaseDefinitionToMigrateTo(caseDefinitionKey, caseDefinitionVersion);
documentBuilder.setTenantId(getJsonProperty(TO_CASE_DEFINITION_TENANT_ID_JSON_PROPERTY, rootNode));
return documentBuilder.build();
} catch (JacksonException e) {
throw new FlowableException("Error parsing Historic Case Instance Migration Document", e);
}
}
protected static String getJsonProperty(String propertyName, JsonNode jsonNode) {
if (jsonNode.has(propertyName) && !jsonNode.get(propertyName).isNull()) {
return jsonNode.get(propertyName).asString();
}
return null;
}
protected static Integer getJsonPropertyAsInteger(String propertyName, JsonNode jsonNode) {
if (jsonNode.has(propertyName) && !jsonNode.get(propertyName).isNull()) {
return jsonNode.get(propertyName).asInt();
}
return null;View on GitHub (pinned to d6d39ce1c6)