Skip to content

fix(push-publishing): don't fail bundle on archived multi-language HTML pages (#36051)#36380

Open
dsilvam wants to merge 1 commit into
mainfrom
issue-36051-archived-multilang-page-pp
Open

fix(push-publishing): don't fail bundle on archived multi-language HTML pages (#36051)#36380
dsilvam wants to merge 1 commit into
mainfrom
issue-36051-archived-multilang-page-pp

Conversation

@dsilvam

@dsilvam dsilvam commented Jul 1, 2026

Copy link
Copy Markdown
Member

Proposed Changes

  • Fix ESContentletAPIImpl.updateTemplateInAllLanguageVersions so it no longer throws DotDataException: Contentlet is currently marked as 'Archived'. when the only existing versions of an HTML page identifier are archived. On the push-publishing receiver, language versions of the same page are processed sequentially — once the first version is saved and archived, checking in the second version found only the archived first version and threw, aborting the entire bundle. Template propagation is meaningless for archived pages, so the method now logs a warning and returns (mirroring the sibling NotFoundInDbException path already swallowed at the call site) instead of throwing.
  • Add an early return when the incoming contentlet is itself archived (defensive guard for the direct-checkin path).
  • Add integration test PublisherTest#testPushArchivedMultiLanguageHTMLPage that push-publishes an archived English + Spanish HTML page and asserts the bundle succeeds and both language versions are archived on the receiver.

Fixes #36051

Checklist

  • Tests
  • Translations
  • Security Implications Contemplated (add notes if applicable)

Additional Info

Root cause: updateTemplateInAllLanguageVersions runs on every HTML-page checkin (only does work when the content type has a TEMPLATE_FIELD). It first searches for a non-archived version of the identifier; when none exists it retries with includeArchived=true. If that finds an archived version it used to throw — but unlike NotFoundInDbException, the DotDataException was not caught in internalCheckin, so it propagated up through ContentHandler.saveContent and failed the whole bundle. This commonly surfaces when push-publishing an entire Site containing archived multi-language pages.

The method is private with a single caller (internalCheckin), so removing the throw affects no external callers.

🤖 Generated with Claude Code

…ML pages (#36051)

updateTemplateInAllLanguageVersions threw a DotDataException when the only
existing versions of an HTML page identifier were archived. On the push
publishing receiver, language versions are processed sequentially: once the
first version is saved and archived, checking in the second version found only
the archived first version and threw, aborting the entire bundle. Template
propagation is meaningless for archived pages, so skip it (log + return)
instead of throwing, matching the sibling NotFoundInDbException handling.

Adds PublisherTest#testPushArchivedMultiLanguageHTMLPage covering an archived
English + Spanish HTML page pushed to the receiver.

Refs: #36051

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@claude

claude Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

Claude finished @dsilvam's task in 5m 21s —— View job


dotCMS Backend Review Pipeline

  • Load dotCMS conventions
  • Get the Java diff
  • Run 4 specialized sub-agents in parallel (Security, Database, Java Standards, REST API)
  • Consolidate findings
  • Post review comment

Summary: 1 medium finding, no critical or high issues. Review posted at #issuecomment-4853939316. The dotBot false positive (format mismatch) was dismissed — the format string has exactly one %s and one matching argument.

@github-actions

github-actions Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

🤖 dotBot Review (Bedrock)

Reviewed 2 file(s); 1 candidate(s) → 1 confirmed, 0 uncertain (unverified, kept for review).

Confirmed findings

  • 🟡 Medium dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImpl.java:6829 — String format mismatch in log message
    The log message at line 6829 has 2 placeholders but only 1 argument provided. The message 'Contentlet with identifier {} is archived, skipping template update for inode {}' expects both identifier and inode values but only contentlet.getIdentifier() is passed, leading to MissingFormatArgumentException when logged.

us.deepseek.r1-v1:0 · Run: #28513782544 · tokens: in: 10616 · out: 2936 · total: 13552 · calls: 4 · est. ~$0.030

@claude

claude Bot commented Jul 1, 2026

Copy link
Copy Markdown
Contributor

🔍 dotCMS Backend Review

[🟡 Medium] dotCMS/src/main/java/com/dotcms/content/elasticsearch/business/ESContentletAPIImpl.java:6833

The else { return; } branch after the isArchived() check has no comment and is structurally misleading. When findContentletByIdentifierAnyLanguage(id, true) returns a non-null contentlet that is not archived (possible when the variant-scoped earlier call missed a live version in another language), this branch silently skips template propagation without logging — making it indistinguishable from the archived path on the outside. Both branches return but only one logs, so the control flow looks like a bug where a case was forgotten.

} else if (contentletByIdentifierAnyLanguageArchived.isArchived()) {
    Logger.warn(ESContentletAPIImpl.class, String.format(
            "Skipping template propagation: all existing versions of Contentlet"
                    + " '%s' are archived.", contentlet.getIdentifier()));
    return;
} else {
    return;   // silent return — no explanation, no log
}

💡 Collapse the two returns and guard only the log on isArchived():

if (contentletByIdentifierAnyLanguageArchived.isArchived()) {
    Logger.warn(ESContentletAPIImpl.class, String.format(
            "Skipping template propagation: all existing versions of Contentlet"
                    + " '%s' are archived.", contentlet.getIdentifier()));
}
// Both archived and unrelated-live fallback: nothing to propagate.
return;

dotBot finding at line 6829 — dismissed (false positive)

dotBot flagged "2 placeholders but only 1 argument" — the actual format string "Skipping template propagation: all existing versions of Contentlet '%s' are archived." has exactly one %s and exactly one argument (contentlet.getIdentifier()). No format mismatch exists.


Next steps

  • 🟡 You can ask me to handle the mechanical simplification: @claude fix the else-return dead branch in ESContentletAPIImpl.java
  • Every new push triggers a fresh review automatically

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AI: Safe To Rollback Area : Backend PR changes Java/Maven backend code

Projects

Status: No status

Development

Successfully merging this pull request may close these issues.

Push publishing archived HTML pages with multiple language versions fails on receiver

2 participants