Skip to content

Task form submit fails with "Must provide 'null' or String value for value of SerializableValue type 'Json'" when instance has Json/Object variables #92

Description

@javahippie

Summary

Completing a task with a form-js form fails with an engine error when the process instance carries any Json/Object variable — even though that variable is not part of the form:

{"type":"InvalidRequestException","message":"Cannot submit task form <id>: Must provide 'null' or String value for value of SerializableValue type 'Json'.","code":null}

Steps to reproduce

  1. Process instance with a Json (or Object) variable and a user task with a deployed form-js form that does not reference that variable.
  2. Open the task in the tasklist, fill the form, click "Complete task".

Observed

The submit payload contains all task variables (in a real test: 20 variables for a form with 6 fields), including untouched Json/Object variables with their deserialized object values. The engine rejects deserialized SerializableValues on submit → the task cannot be completed at all.

Root cause (src/components/TaskForm.jsx + TaskForm_helpers.js)

  • CamundaTaskForm loads /task/{id}/form-variables without a filter → returns every variable of the task scope, Json/Object deserialized as real objects.
  • vars_to_form_data flattens all of them into the form-js initial data. form-js only renders the schema-bound fields (which is why the extra variables are invisible), but echoes the complete data object back on submit.
  • form_data_to_vars converts every entry back with its original type → { "value": {…}, "type": "Json" } → engine rejects (SerializableValues must be submitted as serialized String or null).

Suggested fix

Prototyped locally: restrict both directions to the variables the form actually binds.

/** Collect variable names bound by a form-js schema (incl. nested groups). */
export const schema_variable_keys = (schema) => {
  const keys = new Set();
  const walk = (components) => {
    for (const c of components ?? []) {
      if (c.key) keys.add(c.key.split(".")[0]); // path keys: engine variable is the first segment
      if (c.components) walk(c.components);
    }
  };
  walk(schema?.components);
  return keys;
};

vars_to_form_data(vars, allowed) / form_data_to_vars(data, originalVars, allowed) get an optional Set parameter and skip everything else; CamundaTaskForm passes schema_variable_keys(schema) on both calls. Untouched variables stay server-side — which also matches the semantics of the legacy tasklist (a task complete only writes the form's variables).

Follow-ups worth considering:

  • Filter server-side instead via GET /task/{id}/form-variables?variableNames=... once the schema keys are known.
  • The same round-trip risk applies to any future form-js start form support.

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