dotCMS / dotCMS/core

Block Editor field corruption causes entire page/contentlet to become inaccessible instead of degrading gracefully

Open
#36,297 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

OKR : Customer Support Team : Maintenance Type : Defect
Dominant language
Java
Stars
970
Forks
486
Avg merge
3d 33m
Merged PRs (30d)
170

Description

Problem Statement

When a contentlet has a Block Editor (StoryBlock) field with corrupted or malformed JSON, some code paths in the platform throw an unhandled exception that makes the entire page or contentlet return null/404 — rather than isolating the failure to the corrupted field and continuing to serve the rest of the content.

This was observed in the April 7, 2026 incident (Freshdesk #36268) where ALL `/case-studies/*` pages returned 404 publicly and null in the Page API and GraphQL because a single contentlet had a corrupted Block Editor field. A single broken field took down every page that included that contentlet.

Steps to Reproduce

  1. Create a contentlet with a Block Editor (StoryBlock) field
  2. Corrupt the JSON value of that field directly in the database or via a failed save
  3. Request any page that includes that contentlet via `/api/v1/page/json/{url}` or GraphQL
  4. Observe the entire page returns null/404 instead of rendering with the field as null

Root Cause

The platform has inconsistent exception handling across code paths when processing Block Editor fields:

Protected (correct behavior)
Class Behavior
StoryBlockViewStrategy.transform() Catches JsonProcessingException, puts null in map, continues transformation. This is the reference pattern.
ContentMap.get() Generic catch block swallows the exception and returns null for the field, allowing Velocity rendering to continue.
Unprotected (exception propagates)
Class Issue
ContentToStringUtil.parseBlockEditor() Calls new StoryBlockMap(val) with no try-catch. A malformed Block Editor JSON throws JSONException uncaught, propagating through parseField()parseFields()turnContentletIntoString(), affecting AI indexing, search operations, and potentially GQL resolution.
GraphQL contentlet resolvers Likely do not route through StoryBlockViewStrategy, so the protection it provides does not apply. This explains why the April 7 incident showed null in both Page API and GQL. Needs audit.

Relevant files:

  • dotCMS/src/main/java/com/dotmarketing/portlets/contentlet/transform/strategy/StoryBlockViewStrategy.java — reference pattern, already correct
  • dotCMS/src/main/java/com/dotcms/ai/util/ContentToStringUtil.javaparseBlockEditor() method, unprotected
  • dotCMS/src/main/java/com/dotcms/rendering/velocity/viewtools/content/StoryBlockMap.java — constructors throw JSONException
  • GraphQL contentlet resolvers — need audit

Acceptance Criteria

  • ContentToStringUtil.parseBlockEditor() catches JSONException/Exception from StoryBlockMap construction and returns Optional.empty() instead of propagating the exception
  • GraphQL contentlet resolvers are audited to confirm they either route through StoryBlockViewStrategy or have equivalent protection for Block Editor fields
  • A page containing a contentlet with a corrupted Block Editor field returns the page with that field as null, not a 404 or null page
  • Integration test added: contentlet with malformed Block Editor JSON → Page API returns contentlet with the field as null, rest of page unaffected

dotCMS Version

Observed on corpsites instance (cloud). Affects all versions where Block Editor fields are in use.

Severity

High - Major functionality broken

A single corrupted field in one contentlet can silently take down all pages that include that contentlet, with no warning in the CMS admin and no graceful degradation for end users.

Links

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Begin with ContentToStringUtil.java and its parseBlockEditor() call, then compare its handling with StoryBlockViewStrategy.java and inspect StoryBlockMap.java constructors. Audit the GraphQL contentlet resolver entry points and existing Page API integration tests. Done means malformed Block Editor JSON leaves that field null while the contentlet and containing page remain available through Page API and GraphQL.

Written by the indexing model from the issue text.

Assessment

Tech stack
graphql, java
Domain
api, backend, testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Quiet
Clarity
Mostly clear
Newbie friendliness
48/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.