Skip to content

Workflow fire endpoint returns misleading ClassCastException for array-valued checkbox fields #34815

@fmontes

Description

@fmontes

Problem Statement

The workflow fire endpoint PUT /api/v1/workflow/actions/default/fire/PUBLISH returns a misleading ClassCastException when checkbox or multi-select fields are sent as JSON arrays instead of comma-separated strings. The error message gives no indication of the actual problem -- it looks like an internal server error rather than a client input validation issue.

Error returned:

{"message":"class java.util.LinkedHashMap cannot be cast to class com.dotmarketing.portlets.contentlet.model.Contentlet"}

This is confusing for API consumers because:

  1. The error mentions LinkedHashMap and Contentlet -- internal implementation details unrelated to the user's mistake
  2. There is no mention of which field is problematic or what format is expected
  3. It returns as a 500-level error when it should be a 400 Bad Request with a clear validation message

Steps to Reproduce

  1. Send a PUT request to /api/v1/workflow/actions/default/fire/PUBLISH with checkbox fields as JSON arrays:
{
  "contentlet": {
    "contentType": "Blog",
    "identifier": "0edfee78-2a75-4f3d-bf20-813aae15d4e9",
    "languageId": "1",
    "title": "Test Blog Post",
    "searchEngineIndex": ["index", "follow", "snippet"],
    "sitemap": ["true"]
  }
}
  1. Observe the error response:
{"message":"class java.util.LinkedHashMap cannot be cast to class com.dotmarketing.portlets.contentlet.model.Contentlet"}
  1. The workaround is to send checkbox values as comma-separated strings instead:
{
  "contentlet": {
    "searchEngineIndex": "index,follow,snippet",
    "sitemap": "true"
  }
}

Acceptance Criteria

  • When checkbox/multi-select fields are sent as JSON arrays, the API should either:
    • (Option A - Preferred) Automatically convert JSON arrays to comma-separated strings internally (e.g., ["index", "follow"] -> "index,follow")
    • (Option B) Return a clear 400 Bad Request with a message like: "Field 'searchEngineIndex' is a checkbox field and expects a comma-separated string (e.g., 'index,follow,snippet'), but received an array"
  • The ClassCastException should never bubble up to the API consumer -- it should be caught and translated to a meaningful error
  • Add type-safety checks in groupContentletsByLanguage() to prevent ClassCastException even if unexpected types reach that code path

Root Cause Analysis

The issue flows through these components:

  1. MapToContentletPopulator.processMap() (line ~129-162): Receives the raw field map and passes it to getContentletRelationships() before field type validation occurs
  2. MapToContentletPopulator.getContentletRelationships() (line ~692-803): Iterates over all relationships for the content type and checks the raw map for matching keys. When non-string values (arrays from checkbox fields) are present in the map, they can interfere with relationship processing
  3. ESContentletAPIImpl.groupContentletsByLanguage() (line ~8832-8841): Performs Collectors.toMap(Contentlet::getIdentifier, ...) which throws ClassCastException when non-Contentlet objects (LinkedHashMap) are in the records list

Key files:

  • dotCMS/src/main/java/com/dotcms/rest/MapToContentletPopulator.java
  • dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImpl.java
  • dotCMS/src/main/java/com/dotcms/rest/api/v1/workflow/WorkflowResource.java

dotCMS Version

Latest from main branch (also reproducible on current cloud environments)

Severity

Medium - Some functionality impacted

Links

NA

Metadata

Metadata

Assignees

Type

No type

Projects

Status

New

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions