Merge ExecModule
Overview
MergeModule version 2.0.0 combines one or more workflow objects or arrays in a stable source order. It is a local, side-effect-free transformation: it does not need network access or an IntegrationAccount, and it never writes to an external system.
Version 2 replaces catalog metadata that exposed zero inputs, malformed output names, and only one generic configuration field. It also rejects missing sources, mixed types, malformed keyed records, duplicate source paths, invalid strategies, unsafe aliases, excessive nesting, and result-limit breaches without returning partial data.
Usage
- Put the object or array values in workflow state.
- Configure
sourcesas an ordered JSON array of paths to those values. - Choose a conflict
strategyfor object fields or duplicate keyed array records. - For arrays, set
merge_keyto coalesce object records by a nested key; omit it to concatenate. - Set
max_output_itemsandmax_depthfor the downstream workload. - Read the result from canonical
data; arrays are also available asitems. The configuredoutput_fieldis a compatibility alias.
Inputs
| Name | Type | Required | Limit | Description |
|---|---|---|---|---|
sources | objects or arrays | Yes | 1–32 source paths | Values resolved from the ordered sources configuration. |
Every resolved value must be an object, or every value must be an array. Mixing object and array sources fails the complete execution. In keyed-array mode, every item must be an object with a non-null value at merge_key.
Outputs
| Name | Type | Condition | Description |
|---|---|---|---|
status | string | Always | success or error. |
data | object or array | Success | Canonical merged result. |
items | array | Array success | Canonical array result. |
merged_data | object or array | Default alias | Compatibility alias selected by the default output_field. |
count | integer | Success | Top-level object fields or array items in the result. |
sourceCount | integer | Success | Number of validated sources. |
mode | string | Success | object, array_concat, or array_by_key. |
errorCode | string | Error | Stable machine-readable failure code. |
error | string | Error | Safe, actionable failure message. |
IntegrationAccount Requirements
None. MergeModule operates only on in-memory workflow data and must not receive credentials. Merged data is classified as confidential because combining records can increase sensitivity; downstream workflows must preserve normal ACL and data-handling controls.
Configuration
| Field | Type | Required | Default | Description |
|---|---|---|---|---|
sources | JSON array | Yes | — | Ordered workflow paths such as payload.profile. |
strategy | select | Yes | overwrite | overwrite, keep, merge, or array. |
deep_merge | boolean | No | true | Recursively merge nested objects when strategy is merge. |
merge_key | text | No | empty | Nested key for coalescing array records, such as identity.id. |
output_field | text | No | merged_data | Compatibility alias for canonical data. |
max_output_items | integer | No | 10000 | Maximum result items or top-level object fields; hard cap 100,000. |
max_depth | integer | No | 16 | Maximum copied or recursively merged container depth; hard cap 32. |
Paths support object segments and bounded zero-based indexes, such as payload.groups[0].members. Paths are at most 256 characters. Output aliases are at most 128 characters and cannot shadow canonical status, result, or error fields.
Operations
Object merge
Object fields are visited in source order. First-seen field order is preserved.
| Strategy | Conflict behavior |
|---|---|
overwrite | The later value replaces the earlier value. |
keep | The first value remains. |
merge | Nested objects merge recursively when deep_merge is true; other later values replace earlier values. |
array | Conflicting values are collected into one array; existing arrays are flattened one level. |
Array concatenation
When merge_key is empty, arrays are concatenated in source order. Items retain their original order.
Array merge by key
When merge_key is configured, every item must be an object containing that key. The first occurrence establishes output order. Later records with the same key are combined using the selected strategy. Missing keys and primitive items are rejected rather than silently discarded.
Errors and Failure Modes
| Error code | Cause | Recovery |
|---|---|---|
VALIDATION_ERROR | Invalid source list, path, alias, boolean, integer, or duplicate source path. | Correct the named configuration. |
INVALID_STRATEGY | strategy is unsupported. | Choose one of the four documented strategies. |
SOURCE_LIMIT_EXCEEDED | More than 32 source paths were configured. | Partition the merge into bounded stages. |
MISSING_SOURCE | A configured workflow path is absent or null. | Populate the source or remove the path deliberately. |
TYPE_MISMATCH | Object and array sources were mixed. | Normalize all sources to one top-level type. |
INVALID_RECORD | Keyed-array mode received a primitive item or an object with a non-string field name. | Normalize the record before merging. |
MISSING_MERGE_KEY | A keyed-array record has no non-null merge key. | Populate the key or use concatenation mode. |
RESULT_LIMIT_EXCEEDED | The result exceeds max_output_items. | Filter, partition, or deliberately raise the bound. |
DEPTH_LIMIT_EXCEEDED | Nested data exceeds max_depth. | Flatten the source or deliberately raise the bound. |
EXECUTION_ERROR | An unexpected local failure occurred. | Preserve inputs, inspect sanitized diagnostics, and fix the defect before retrying. |
Failures clear partial results. Event logs contain only mode, count, or stable error code—not merged payloads.
Example
Configuration:
{
"sources": ["payload.profile", "payload.preferences"],
"strategy": "merge",
"deep_merge": true,
"output_field": "customer",
"max_output_items": 100,
"max_depth": 12
}
Input:
{
"payload": {
"profile": {
"id": "u-1",
"contact": {"name": "Ada", "email": "ada@example.com"}
},
"preferences": {
"contact": {"locale": "en-US"},
"marketingOptIn": true
}
}
}
Expected result:
{
"status": "success",
"data": {
"id": "u-1",
"contact": {
"name": "Ada",
"email": "ada@example.com",
"locale": "en-US"
},
"marketingOptIn": true
},
"customer": {
"id": "u-1",
"contact": {
"name": "Ada",
"email": "ada@example.com",
"locale": "en-US"
},
"marketingOptIn": true
},
"count": 3,
"sourceCount": 2,
"mode": "object"
}
Notes
- Pagination: none. Inputs are already-materialized workflow values; partition large data upstream.
- Limits: 32 sources, 256-character paths, 100,000 hard maximum output items, and depth 32.
- Idempotency: natural and deterministic for the same ordered inputs and configuration.
- Input mutation: nested objects and arrays are copied into the result; the module does not mutate source containers.
- Rate limits: none; no provider is called.
- API constraints: keyed equality follows Java object equality after workflow deserialization. Numeric
7and string"7"are distinct keys. - Destructive behavior: none. No record is created, updated, or deleted outside workflow memory.
- Testing boundary: focused tests cover recursive object merge, copy isolation, deterministic keyed arrays, limits, malformed records, missing sources, depth, aliases, and metadata serialization.
- Runtime boundary: merged source, production documentation, public launch content, and deployed
/v1/modules/metadataremain separate delivery states.
See the ExecModule catalog and the neighboring Join module.