Skip to content

fix(cli): flow update --handler-config corrupts params to empty string in flow_step_settings #2059

@chubes4

Description

@chubes4

Summary

wp datamachine flow update <flow_id> --step=<flow_step_id> --handler-config='<json>' accepts the JSON, writes the handler_config.params correctly, but also writes a separate flow_step_settings block where params becomes an empty string instead of the nested object. When the SystemTaskStep later runs and reads flow_step_settings.params (which it prefers over handler_config.params), it gets "" and crashes at array_merge():

```
PHP Fatal error: array_merge(): Argument #1 must be of type array, string given
in /var/www/.../data-machine/inc/Core/Steps/SystemTask/SystemTaskStep.php:211
```

Reproduction

```bash

1. Take any flow with a system_task step. Verify it currently works.

wp datamachine flow get 4 --format=json | jq '.flow_config[].handler_config'

2. Update the handler_config via CLI:

wp datamachine flow update 4 \
--step=4_56672089-8854-4b48-a6ed-df261aea7442_4 \
--handler-config='{"task":"dispatch_message","params":{"channel":"kimaki","recipient":"123","message":"test"}}'

3. Inspect the result:

wp datamachine flow get 4 --format=json | jq '.flow_config[]'
```

Expected: flow_step_settings.params is the same nested object as handler_config.params.

Actual: flow_step_settings.params == "" (empty string), even though handler_config.params is correct.

Impact

  • Any flow reconfigured via CLI breaks at runtime because the engine reads flow_step_settings.params first (FlowStepConfig::getHandlerConfig() at L290) and never falls through to handler_config.params.
  • Discovered while reconfiguring flow Chat responses are slow and may never appear #4 to use dispatch_message instead of agent_call for the agent-pings architecture rework. Worked around by writing both handler_config AND flow_step_settings via direct DB call.

Likely cause

FlowsCommand::update_flow() at inc/Cli/Commands/Flows/FlowsCommand.php (~L1175-L1199) takes the parsed handler_config, looks for a single top-level handler-slug key to unwrap, then passes unwrapped_config to UpdateFlowStepAbility. When the JSON looks like {"task": "...", "params": {...}} (two top-level keys), the unwrap branch skips, but flow_step_settings ends up populated from a different code path that loses the nested params value somewhere in the merge.

Likely culprits to inspect:

  • FlowStepConfigFactory::__construct() and the loop at L219 that merges handler_slug, handler_config, flow_step_settings from args — possibly stringifying nested arrays.
  • FlowStepConfigFactory::__construct() L158 fallback: $settings = ! empty( $flow_step_settings ) ? $flow_step_settings : ( is_array( $handler_config ) ? $handler_config : array() ); — if $flow_step_settings is set to ['task' => '...', 'params' => ''] somewhere upstream, this fallback returns the bad shape.
  • UpdateFlowStepAbility and what it passes to db_flows->update_flow().

The bug is upstream of the DB write — both writes happen in the same call.

Workaround in use

Direct DB write via wp eval-file that updates both handler_config AND flow_step_settings to the same nested-array shape. Ugly but unblocks the agent-pings reconfig.

Acceptance criteria

  • wp datamachine flow update <flow_id> --step=<step_id> --handler-config='<json>' writes flow_step_settings.params as the same nested object as handler_config.params.
  • Test coverage: a CLI smoke test that round-trips a system_task flow update and reads back the result, asserting both keys are arrays.
  • No regression on existing flows using the wrapped ({"handler_slug":{...}}) shape.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions