Problem/Motivation

Two interaction plugins report a validation refusal with $form_state->setErrorByName() from inside their validateConfigurationForm(), at three call sites between them. In a subform that names the error rather than the element, and the name it builds does not reach the field it is about.

SubformState::setErrorByName() composes the error name from the subform's #array_parents, while an error is matched to its element by that element's #parents. In Orchestra the two differ, because the classic modeler renders the whole workflow under a structure wrapper and hands the plugin subform a #parents path without it. Measured on the interaction settings subform of a node in the classic modeler:

#parents:       ["nodes","n_task","settings","interaction_settings"]
#array_parents: ["structure","nodes","n_task","settings","interaction_settings"]

So the error is recorded under structure][nodes][n_task][settings][interaction_settings][form_operation and belongs to no element on the page. Two things follow, both silent:

  • the offending field is never marked, so it gets no error styling and no aria-invalid;
  • OrchestraCmForm opens a collapsed node section by matching error keys against ^(nodes|flows)\]\[, and structure][ does not match, so the section holding the field stays shut.

The author is shown the message with nothing on screen to correct, on a form whose sections are collapsed by default.

Each site carries a comment asserting the opposite, that the host "hands the plugin a SubformState, whose setErrorByName() prefixes the subform's own place in the form for us". That is true of what it builds and false of what the error matcher reads.

Steps to reproduce

  1. Author a workflow in the classic modeler with an interaction task node whose interaction is Entity form.
  2. Set its operation to Delete, which the plugin refuses.
  3. Save. The message appears; the node section stays collapsed and the select is not marked.

Proposed resolution

Set the error on the element instead of naming it, which is what the user and email audiences already do:

$form_state->setError($form['form_operation'], $message);

FormState::setError() reads the element's own #parents, so the key matches however deeply the host nests the subform. The three call sites are EntityInteraction::validateConfigurationForm() (form_operation) and WebformInteraction::validateConfigurationForm() (mode and context_display). The comments above them need correcting with the fix.

Remaining tasks

  • Fix all three call sites and their comments.
  • Cover each with a kernel test that drives OrchestraCmForm through the form builder and asserts the error key is the submitted path, since where an error lands is only observable through a real host form.
  • Check whether any other plugin subform names an error rather than setting it. A sweep of every validateConfigurationForm() in the project finds no others: the node features and the condition tree build their keys from #parents by hand, and the plain forms are not subforms.

User interface changes

None beyond the refusal reaching the field it is about: the control is marked and its section opens.

AI-Generated: Yes (Claude Code was used to help draft this issue summary. The behavior described was measured by building the classic modeler form and reading the two parent paths off the interaction settings subform.)

Issue fork orchestra-3624283

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Comments

mably created an issue. See original summary.

mably’s picture

Status: Active » Needs review
mably’s picture

Issue summary: View changes

  • mably committed f27c81fd on 1.x
    fix: #3624283 Set the interaction plugins' validation errors on the...
mably’s picture

Status: Needs review » Fixed

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.