flowable/flowable-engine · error · FlowableException

Programmatic error: field added to unknown element

Error message

Programmatic error: field added to unknown element '${currentCmmnElement}'

What it means

Thrown by ExtensionElementsXMLConverter.readFieldExtension when a <field> extension element is parsed successfully but the current CMMN element's type is not one of the types that accept field extensions. The message says 'programmatic error' because the converter normally guarantees a supported element type; hitting it indicates an internal dispatch gap or an unexpected element on the conversion stack.

Solutions

  1. Inspect which element type is printed in the message and move the <field> extension to a supported parent (task, listener, decision task).
  2. Remove the field extension from the unsupported element.
  3. If it is a legitimate element type, patch/upgrade Flowable so readFieldExtension handles that type (likely a converter bug).

Example fix

<!-- before: field on unsupported element -->
<caseTask id="ct1">
  <extensionElements>
    <flowable:field name="x" stringValue="y"/>
  </extensionElements>
</caseTask>
<!-- after: move field to the listener that needs it -->
<caseTask id="ct1">
  <extensionElements>
    <flowable:taskListener event="end" class="com.acme.Listener">
      <flowable:field name="x" stringValue="y"/>
    </flowable:taskListener>
  </extensionElements>
</caseTask>
Defensive patterns

Strategy: validation

Validate before calling

// Only emit <field> extensions inside elements known to accept them
Set<String> fieldHosts = Set.of("humanTask", "serviceTask", "decisionTask", "caseTask", "processTask", "taskListener", ...
// assert extension parent type ∈ fieldHosts before conversion

Type guard

boolean supportsFieldExtension(BaseElement el) {
    return el instanceof CmmnActivity || el instanceof FlowableListener;
}

Try / catch

try {
    cmmnModel = converter.convertToCmmnModel(stream, encoding);
} catch (FlowableException e) {
    if (e.getMessage().startsWith("Programmatic error: field added to unknown element")) {
        // relocate or remove the field extension on the printed element
    }
    throw e;
}

Prevention

When it happens

Trigger: A <flowable:field> extension placed inside <extensionElements> of a CMMN element type that has no handler branch in readFieldExtension (not a task/listener/decision task etc.). Usually signals a converter bug or an element type added to the stack unexpectedly.

Common situations: Custom/patched Flowable versions where a new element type was not added to readFieldExtension; users copying <field> extensions onto unsupported CMMN elements via hand-edited XML.

Understand the failure class

Background: UnsupportedOperationException and "is not supported" errors: when a library deliberately refuses a call — this error's family across 30 libraries.

Related errors


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

Appendix: source

Thrown at modules/flowable-cmmn-converter/src/main/java/org/flowable/cmmn/converter/ExtensionElementsXMLConverter.java:284

                        readyWithFieldExtension = true;
                    }
                }
            } catch (Exception e) {
                LOGGER.warn("Error parsing field extension child elements", e);
            }
        }

        CmmnElement currentCmmnElement = conversionHelper.getCurrentCmmnElement();
        if (currentCmmnElement instanceof ServiceTask) {
            ((ServiceTask) currentCmmnElement).getFieldExtensions().add(extension);

        } else if (currentCmmnElement instanceof DecisionTask) {
            ((DecisionTask) currentCmmnElement).getFieldExtensions().add(extension);
        } else if (currentCmmnElement instanceof FlowableListener) {
            ((FlowableListener) currentCmmnElement).getFieldExtensions().add(extension);

        } else {
            throw new FlowableException("Programmatic error: field added to unknown element '" + currentCmmnElement + "'");

        }
    }

    protected void readHttpRequestHandler(XMLStreamReader xtr, ConversionHelper conversionHelper) {
        BaseElement cmmnElement = conversionHelper.getCurrentCmmnElement();
        if (!(cmmnElement instanceof HttpServiceTask)) {
            return;
        }

        FlowableHttpRequestHandler requestHandler = new FlowableHttpRequestHandler();
        setImplementation(xtr, requestHandler);

        ((HttpServiceTask) cmmnElement).setHttpRequestHandler(requestHandler);
    }

    protected void readHttpResponseHandler(XMLStreamReader xtr, ConversionHelper conversionHelper) {
        BaseElement cmmnElement = conversionHelper.getCurrentCmmnElement();

View on GitHub (pinned to d6d39ce1c6)