Skip to content

Content Types: Fix property variation change when content exists only in non-default language#21182

Merged
AndyButland merged 2 commits intomainfrom
fix/property-variation-change-non-default-language-11771
Dec 17, 2025
Merged

Content Types: Fix property variation change when content exists only in non-default language#21182
AndyButland merged 2 commits intomainfrom
fix/property-variation-change-non-default-language-11771

Conversation

@nikolajlauridsen
Copy link
Contributor

@nikolajlauridsen nikolajlauridsen commented Dec 17, 2025

Summary

Fixes #11771

This PR fixes a PanicException that was thrown when changing a property type's variation setting (e.g., from invariant to "Vary by culture") when content exists only in a non-default language.

Root Cause Analysis

The Scenario

  1. A multilingual site has English (default) and Danish languages
  2. Content is created only in Danish (non-default language)
  3. The content type has an invariant property (e.g., a textbox)
  4. An editor changes that property to "Vary by culture"
  5. Result: PanicException is thrown

Why This Happens

When a property type's variation changes, ContentTypeRepositoryBase.RenormalizeDocumentEditedFlags performs two key operations:

  1. CopyPropertyData: Migrates property data to the appropriate location

    • For invariant → variant: copies data to the default language (LanguageId = defaultLanguageId)
    • For variant → invariant: copies data from the default language to invariant (LanguageId = null)
  2. RenormalizeDocumentEditedFlags: Updates the "edited" flags for affected documents

    • Groups property data by (nodeId, languageId)
    • For each group, finds the corresponding DocumentCultureVariationDto to update its edited flag

The Bug

After CopyPropertyData migrates invariant property data to the default language, RenormalizeDocumentEditedFlags tries to find a DocumentCultureVariationDto for the default language. However:

  • No DocumentCultureVariationDto exists for the default language because the content was never created in that language
  • The code previously threw a PanicException when it couldn't find the expected record

Why AllowEditInvariantFromNonDefault Affected This

The AllowEditInvariantFromNonDefault setting determines where invariant property data is stored:

Setting Invariant Data Location Why Exception Occurs
true Current/draft version (default language context) Invariant→Variant works, but Variant→Invariant fails
false Published version only Invariant→Variant fails immediately

Both scenarios ultimately hit the same issue: expecting a DocumentCultureVariationDto that doesn't exist.

The Fix

Changed the PanicException to a continue statement in RenormalizeDocumentEditedFlags.

Why this is safe: The purpose of this code is to update the "edited" flag on DocumentCultureVariationDto records. If no such record exists for a language (because content was never created in that language), there's simply nothing to update. The property data migration itself succeeds - we just skip the edited flag update for non-existent language variants.

// Before: threw PanicException
else if (ev.Key.langId.HasValue)
{
    throw new PanicException($"Could not find the document culture ...");
}

// After: skip updating edited flag for non-existent language variants
else if (ev.Key.langId.HasValue)
{
    // This can happen when a property changes from invariant to variant and the content
    // was only created in non-default languages. The invariant property data gets migrated
    // to the default language, but no DocumentCultureVariationDto exists for the default
    // language because the content was never created in that language.
    // In this case, we simply skip updating the edited flag since there's no document
    // culture variation record to update.
    continue;
}

Test Plan

Added 20 new integration test cases covering both AllowEditInvariantFromNonDefault = false (default) and AllowEditInvariantFromNonDefault = true:

With AllowEditInvariantFromNonDefault = false (default)

  • Invariant → Variant property change with content only in non-default language (4 cases)
  • Variant → Invariant property change with content only in non-default language (4 cases)
  • Round-trip variation changes (Invariant → Variant → Invariant)
  • Content type variation changes when content only exists in non-default language

With AllowEditInvariantFromNonDefault = true

  • Invariant → Variant property change with content only in non-default language (4 cases)
  • Variant → Invariant property change with content only in non-default language (4 cases)
  • Round-trip variation changes (Invariant → Variant → Invariant)
  • Content type variation changes when content only exists in non-default language

All 105 tests in ContentTypeServiceVariantsTests pass (85 existing + 20 new regression tests).

🤖 Generated with Claude Code

… in non-default language (closes #11771)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>
Copilot AI review requested due to automatic review settings December 17, 2025 10:47
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR fixes a PanicException that occurred when changing a property type's variation (e.g., from invariant to culture-variant) in scenarios where content exists only in non-default languages. The issue stemmed from the system attempting to update DocumentCultureVariationDto records that don't exist for languages in which content was never created.

Key Changes:

  • Replaced a PanicException with a continue statement to gracefully handle missing DocumentCultureVariationDto records
  • Added comprehensive test coverage for property and content type variation changes in edge-case scenarios

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/Umbraco.Infrastructure/Persistence/Repositories/Implement/ContentTypeRepositoryBase.cs Changed exception handling in RenormalizeDocumentEditedFlags to skip updating edited flags for non-existent language variant records instead of throwing PanicException
tests/Umbraco.Tests.Integration/Umbraco.Infrastructure/Services/ContentTypeServiceVariantsTests.cs Added 10 new test cases covering property variation changes (invariant↔variant) and content type variation changes when content exists only in non-default languages

@AndyButland
Copy link
Contributor

This all looks great @nikolajlauridsen in terms of updates, analysis and tests. The only problem is I'm struggling to replicate the original issue to verify that this does indeed solve it. Please could you add manual replication steps, including details of the AllowEditInvariantFromNonDefault setting, that I should follow to see the issue? I know it's kind of described above and also on the original issue, but I must be missing something when I follow that as I can't seem to trigger the exception.

While I'm looking that, my only thought on the tests you might consider, was that would it be good to have variations with the two options for the AllowEditInvariantFromNonDefault setting?

@nikolajlauridsen
Copy link
Contributor Author

The setup I used for testing was:

  1. Create a document type that varies by culture
  2. Add a checkbox property which is shared between cultures (invariant), I think the property type is relevant here
  3. Add an additional language, I chose Danish
  4. Create a piece of content only in the non default language (danish)
  5. Change the property to not be shared between cultures (varying)

If I had AllowEditInvariantFromNonDefault set to false I get an error when I initially change the property to no longer be shared between cultures, if I set it to true I get the same error when I change it back to be invariant, so initially invariant then variant then invariant again -> error occurs

I think it's a good idea to add tests with AllowEditInvariantFromNonDefault set to true, because it's actually the primary place it might happen, if it's set to false it'll only happen if you use something like checkbox becaues it has a default value, but if it's set to true it can also happen with a textstring because the editor can change it manually 😄

Copy link
Contributor

@AndyButland AndyButland left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @nikolajlauridsen - I've got it now. Did seem that the property type was important. Can confirm I no longer see the problem though with this PR included, and the integration tests look good to me now coverage wise.

@AndyButland AndyButland merged commit 638e181 into main Dec 17, 2025
25 of 26 checks passed
@AndyButland AndyButland deleted the fix/property-variation-change-non-default-language-11771 branch December 17, 2025 14:18
AndyButland pushed a commit that referenced this pull request Dec 17, 2025
… in non-default language (#21182)

* Content Types: Fix property variation change when content exists only in non-default language (closes #11771)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

* Add tests for AllowEditInvariantFromNonDefault enabled scenario

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

---------

Co-authored-by: Claude Opus 4.5 <[email protected]>
AndyButland pushed a commit that referenced this pull request Dec 17, 2025
… in non-default language (#21182)

* Content Types: Fix property variation change when content exists only in non-default language (closes #11771)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

* Add tests for AllowEditInvariantFromNonDefault enabled scenario

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <[email protected]>

---------

Co-authored-by: Claude Opus 4.5 <[email protected]>
@AndyButland
Copy link
Contributor

Have cherry-picked for 16.5 and 17.1.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Issue when enabling Check box property as variant: The existing DocumentCultureVariationDto was not found for node XXXX and language X

2 participants