Fixing TinyMCE Initialization Failures in Optimizely CMS: A Hidden Pipeline Issue with .NET SDK Versions

Over the past few weeks, several Optimizely CMS projects began experiencing a puzzling failure: XHtmlString fields stopped initializing TinyMCE in the edit interface. The editor simply refused to load, leaving users unable to manage rich text content.

This issue surfaced in multiple unrelated projects, so it was clear the root cause wasn’t project-specific code. After some investigation, we traced the failure to something unexpected: the .NET SDK version used by the Azure DevOps build pipeline.

The Symptom

Projects deployed to Optimizely DXP began showing:

  • TinyMCE not initializing for XHtmlString fields
  • The editor window appearing as plain text
  • No console error tied directly to TinyMCE
  • A dependency resolution warning pointing to the generated .deps.json file

Locally everything worked flawlessly, which made the issue even more confusing.

The Root Cause: Azure DevOps Was Building with .NET 10

The real issue turned out to be that the Azure DevOps pipeline was using .NET SDK 10.0.100, a preview/next-gen SDK that is not compatible with Optimizely CMS 12.

This resulted in a different .deps.json file being generated during dotnet publish. That file included unexpected reference assemblies and compileOnly entries that prevented the Optimizely UI framework — including TinyMCE — from loading correctly in DXP.

Optimizely CMS 12 is designed and tested for .NET 6 and .NET 8, not .NET 10.

How to Confirm Your Pipeline Is Using the Wrong SDK

Add this step temporarily in your Azure DevOps pipeline:

- script: dotnet --info
  displayName: "Show .NET SDK info"

When the pipeline runs, check the output.

If you see something like:

.NET SDK:
 Version: 10.0.100

then your pipeline is using the wrong SDK — and that is the root of the TinyMCE failure.

The Fix: Pin the Pipeline to .NET 8

To ensure consistency with local builds and compatibility with DXP, add the following step before restore/build in your pipeline:

- task: UseDotNet@2
  displayName: "Use .NET 8 SDK"
  inputs:
    packageType: 'sdk'
    version: '8.0.x'

This forces the pipeline to install and use the correct .NET 8 SDK, ensuring that:

  • The same dependency graph is produced locally and in DevOps
  • .deps.json is generated correctly
  • TinyMCE initializes normally in the Optimizely edit interface

After applying this fix, projects deployed successfully and TinyMCE loaded without issues.

Why This Happens

The hosted agent windows-latest recently began shipping with .NET 10 preview SDKs preinstalled.
If your pipeline does not explicitly specify a .NET version, Azure DevOps defaults to the newest available SDK, even if your project was built for .NET 8.

This means the SDK influences:

  • Dependency resolution
  • Runtime asset inclusion
  • .deps.json generation

Tiny differences here can break runtime frameworks like the Optimizely UI.

Recommended Best Practices

To prevent similar issues in the future:

✔ Always pin your SDK in the pipeline

Use UseDotNet@2 explicitly.

✔ Add a global.json in your project root

Example:

{
  "sdk": {
    "version": "8.0.403",
    "rollForward": "disable"
  }
}

This ensures both local and CI environments use the same SDK.

✔ Periodically check your build logs

Using dotnet --info during troubleshooting helps detect unintended version changes early.

Conclusion

This TinyMCE initialization issue turned out to be a great example of how build environments silently affect runtime behavior. Even when the application compiles and publishes successfully, an unexpected SDK version can introduce subtle changes that break functionality in production.

By explicitly pinning your .NET SDK to version 8 in Azure DevOps (and ideally through a global.json file), you ensure consistent behavior across environments and avoid issues like this one.

If you encounter similar UI issues in Optimizely, checking the SDK version in your pipeline should be one of the first steps.

Leave a comment