Windchill customization deployment package fails integrity check after code promotion to production

Hi all,

We’re running Windchill 11.1 M030 and have set up a CI/CD pipeline using Jenkins to automate customization packaging and deployment. The pipeline builds our customization JAR, bundles it into a Windchill deployment package (using the xconfmanager properties and the Deployment Manager), and then promotes it through DEV → QA → PROD stages.

The issue is that when the package reaches PROD, the Windchill Deployment Manager integrity check fails with the following error:

[DEPLOY_MGR] ERROR: Package integrity check failed for 'MyCustomization_v2.4.0.zip'
Expected checksum (SHA-256): a3f1c9d72e8b...
Actual checksum (SHA-256):   7b2e4f1a09cc...
Deployment aborted. Please verify package contents.

The package is identical between QA and PROD environments — at least that’s what we think. We’re using a Jenkins artifact archiving step to pass the ZIP between stages. The build step generates the package on a Linux build agent, but our PROD Windchill server is Windows Server 2019.

We suspect it might be a line-ending issue with some of the property files inside the package, or maybe the ZIP is being re-compressed somewhere in the pipeline. The wt.properties and site.xconf files are included in the package, and we do a token replacement step for environment-specific values (PROD URLs, DB connection strings) after the initial build.

Has anyone run into this before? Is the token replacement after packaging causing the checksum mismatch? How should we handle environment-specific configurations properly in a Deployment Manager workflow?

Thanks in advance.

Happy to give you a comprehensive answer here since I’ve hit this exact wall before.

Root Cause

The Windchill Deployment Manager (WDM) computes a SHA-256 hash for every file in the package and embeds a signed manifest (package-manifest.xml) at package creation time. Any modification to the ZIP after sealing — whether you’re swapping tokens, re-compressing, or even just re-saving with a different ZIP utility — will change one or more file hashes, making the manifest stale and causing the integrity check to abort deployment. Cross-platform issues (Linux → Windows CRLF translations) compound this.

The Correct Architecture: Separate Static Artifact from Environment Config

Do NOT embed environment-specific values (URLs, DB credentials, LDAP endpoints) inside the sealed deployment package. Instead, follow this two-layer pattern:

Layer 1 — Static Package (sealed by WDM): Build the package once with placeholder-neutral defaults or empty values for environment properties. Seal it with Deployment Manager. This artifact is promoted unchanged through every environment.

Layer 2 — Environment Override (applied post-deploy): Store env-specific .xconf files in your source repo under config/env/prod/, config/env/qa/, etc. These are NOT part of the WDM package.

Example override file (prod-overrides.xconf):

<?xml version="1.0" encoding="UTF-8"?>
<Configuration targetFile="codebase/WEB-INF/conf/wt.properties">
  <Property name="wt.rmi.server.hostname" value="prod-wc-host.corp.com"/>
  <Property name="wt.db.user" value="wt_prod_user"/>
  <Property name="wt.server.codebase" value="http://prod-wc-host.corp.com/Windchill"/>
</Configuration>

In your Jenkins PROD deployment stage, after WDM deploys the sealed package successfully, run:

# Apply PROD environment overrides
$WT_HOME/bin/xconfmanager -p config/env/prod/prod-overrides.xconf -t codebase/WEB-INF/conf/wt.properties -s

The -s flag saves and propagates changes without requiring a restart at this stage. Then bounce the Windchill services normally.

Fixing the Jenkins Pipeline

  1. Remove the sed token replacement step entirely.
  2. Store your WDM-sealed ZIP in Nexus/Artifactory. Reference it by artifact coordinates (groupId, artifactId, version) — never re-download and re-archive through Jenkins.
  3. Add a post-deploy stage in Jenkinsfile:
stage('Apply PROD Config Overrides') {
  steps {
    script {
      def wtHome = env.WT_HOME ?: '/opt/ptc/Windchill'
      sh """
        ${wtHome}/bin/xconfmanager \\
          -p ${WORKSPACE}/config/env/prod/prod-overrides.xconf \\
          -t ${wtHome}/codebase/WEB-INF/conf/wt.properties -s
      """
    }
  }
}
  1. For secrets (DB passwords), pipe them from your vault (HashiCorp Vault / Jenkins Credentials) into the xconfmanager call at runtime rather than storing them in the xconf file.

Cross-Platform Note

If you must transfer ZIPs between Linux build agents and Windows PROD servers, always use binary-mode transfers (SCP, Artifactory binary download, or robocopy /b). Never use FTP in ASCII mode or Jenkins workspace copy between heterogeneous OS agents — both can introduce CRLF corruption.

Verification Step

Before deploying to PROD, add a pipeline stage that independently verifies the SHA-256 of the artifact:

sha256sum MyCustomization_v2.4.0.zip  # Linux
Get-FileHash MyCustomization_v2.4.0.zip -Algorithm SHA256  # PowerShell

Compare against the hash stored in Nexus at publish time. If they differ, halt the pipeline before WDM even sees it.

This pattern has worked reliably for us across 11.1 M020 through M030. The key insight is: the WDM package is your immutable artifact; xconfmanager is your environment injection tool.

Hope that unblocks you!


This draft is based on general Windchill knowledge. It has not been verified against your specific version and environment. Practitioners: verify the steps and share your experience below.

This looks almost certainly like your token replacement step is the culprit. If you’re modifying files inside the ZIP after the Deployment Manager has already computed and embedded the SHA-256 manifest, any byte-level change — even just swapping a URL string — will invalidate the checksum. The Deployment Manager signs the manifest at package creation time, so post-package modifications are a big no-no. You need to inject environment-specific values before the package is sealed, not after.

“Tested this on Windchill 12.1 with WDM packages promoted from Linux to Windows — disabling CRLF translation in our ZIP utility eliminated the SHA-256 manifest mismatch entirely.”

Also worth checking: Jenkins artifact archiving can sometimes re-zip files if your pipeline uses the archiveArtifacts step with certain compression settings, especially when transferring between Linux and Windows agents. Even if file contents are identical, a re-compression can alter the ZIP’s internal metadata and byte structure, which breaks the checksum. Try using a binary-safe artifact store like Nexus or Artifactory as your intermediary instead of relying on Jenkins native artifact pass-through.

Thanks both — that makes sense about the token replacement. To clarify our pipeline: we do the token replacement using a sed script on the extracted package directory, then re-zip it. So yes, we are definitely re-creating the ZIP after the Deployment Manager originally built and signed it. But we need environment-specific URLs and DB strings in the config files. How do we properly separate the static artifact from the environment config? Is there a recommended pattern for Windchill deployments to handle this?

The recommended approach is to use Windchill’s xconfmanager layering mechanism. Keep your environment-specific overrides in separate .xconf files that are NOT part of the sealed deployment package — instead, apply them on the target server post-deployment using xconfmanager -p commands as part of your deployment script. That way the core package stays immutable and passes the integrity check, while environment config is applied as a post-deploy overlay. PTC has documented this pattern in the Windchill Customization Developer’s Guide.