flowable/flowable-engine · error · FlowableException

Error parsing Case Instance Migration Document

Error message

Error parsing Case Instance Migration Document

What it means

CaseInstanceMigrationDocumentConverter.convertFromJson parses a migration document JSON payload with Jackson. Any JacksonException during parsing (malformed JSON, wrong types for fields, unexpected node shapes) is wrapped in this FlowableException.

Solutions

  1. Validate the migration document JSON with a JSON linter/parser before passing it
  2. Compare the document against the expected schema (caseInstanceId, migrateToCaseDefinition, variables, etc.) and fix types/names
  3. Regenerate the document programmatically via CaseInstanceMigrationDocumentBuilder instead of hand-writing it
  4. Ensure the Flowable version producing and consuming the document matches

Example fix

// before
String json = "{ \"migrateToCaseDefinition\": { \"key\": "; // malformed
converter.convertFromJson(json);
// after
String json = "{\"migrateToCaseDefinition\":{\"key\":\"myCase\",\"version\":2}}";
converter.convertFromJson(json);
Defensive patterns

Strategy: try-catch

Validate before calling

let doc;
try { doc = JSON.parse(migrationJson); } catch (e) { throw new Error('Migration document is not valid JSON: ' + e.message); }
if (!doc.migrateToCaseDefinition || !doc.migrateToCaseDefinition.key) throw new Error('Migration document missing migrateToCaseDefinition.key');

Type guard

function isValidMigrationDoc(json) { try { const d = JSON.parse(json); return d != null && typeof d === 'object'; } catch { return false; } }

Try / catch

try { converter.convertFromJson(json); } catch (e) { if (String(e.message).includes('Error parsing Case Instance Migration Document')) { logJsonError(json, e.getCause ? e.getCause() : e); } else { throw e; } }

Prevention

When it happens

Trigger: Calling convertFromJson (e.g. via migration APIs that accept a JSON migration document string) with syntactically invalid JSON, a JSON value of the wrong type (e.g. variables as an array instead of an object), or a corrupted document.

Common situations: Hand-authoring migration JSON with typos; copying document JSON from logs with truncation; version mismatch where the document was produced by a different Flowable version with a changed schema; passing an empty string.

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


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

Appendix: source

Thrown at modules/flowable-cmmn-engine/src/main/java/org/flowable/cmmn/engine/impl/migration/CaseInstanceMigrationDocumentConverter.java:501

                }
            }

            JsonNode caseInstanceVariablesNode = rootNode.get(CASE_INSTANCE_VARIABLES_JSON_SECTION);
            if (caseInstanceVariablesNode != null) {
                Map<String, Object> caseInstanceVariables = convertFromJsonNodeToObject(caseInstanceVariablesNode, objectMapper);
                documentBuilder.addCaseInstanceVariables(caseInstanceVariables);
            }

            String preUpgradeExpression = getJsonProperty(PRE_UPGRADE_EXPRESSION_KEY_JSON_PROPERTY, rootNode);
            documentBuilder.preUpgradeExpression(preUpgradeExpression);

            String postUpgradeExpression = getJsonProperty(POST_UPGRADE_EXPRESSION_KEY_JSON_PROPERTY, rootNode);
            documentBuilder.postUpgradeExpression(postUpgradeExpression);

            return documentBuilder.build();

        } catch (JacksonException e) {
            throw new FlowableException("Error parsing Case Instance Migration Document", e);
        }
    }

    protected static JsonNode convertToJsonCaseInstanceVariables(CaseInstanceMigrationDocument caseInstanceMigrationDocument, ObjectMapper objectMapper) {
        Map<String, Object> caseInstanceVariables = caseInstanceMigrationDocument.getCaseInstanceVariables();
        if (caseInstanceVariables != null && !caseInstanceVariables.isEmpty()) {
            return objectMapper.valueToTree(caseInstanceVariables);
        }
        return null;
    }
    
    protected static <T> T convertFromJsonNodeToObject(JsonNode jsonNode, ObjectMapper objectMapper) {
        return objectMapper.convertValue(jsonNode, new TypeReference<>() {

        });
    }
    
    protected static String getJsonProperty(String propertyName, JsonNode jsonNode) {

View on GitHub (pinned to d6d39ce1c6)