Skip to content

Build timestamp validation reads the wrong MANIFEST.MF when a Java agent is instrumenting the JVM #475

Description

@medonmez

Environment

  • sklearn2pmml: 0.132.0
  • Java: OpenJDK 17.0.20 (Red Hat)
  • Python: 3.9.14
  • scikit-learn: 1.3.2
  • Deployment: enterprise-managed OpenShift / RHCOS container environment
  • Java instrumentation: Dynatrace OneAgent

Problem

sklearn2pmml() fails before the estimator is deserialized with:

com.sklearn2pmml.SkLearn2PMMLException:
The SkLearn2PMML package is not dated

    at com.sklearn2pmml.Main.getBuildTimestamp(Main.java:243)
    at com.sklearn2pmml.Main.validate(Main.java:146)
    at com.sklearn2pmml.Main.main(Main.java:102)

The SkLearn2PMML JAR itself contains a valid build timestamp:

Manifest-Version: 1.0
Build-Timestamp: 2026-06-30T18:45:00Z
Implementation-Title: SkLearn2PMML package
Implementation-Version: 0.132.0

The same SkLearn2PMML JAR and Python package work correctly in another environment without this Java agent instrumentation.

Root cause

The OpenShift environment uses Dynatrace OneAgent process instrumentation.

com.sklearn2pmml.Main is correctly loaded from the SkLearn2PMML JAR:

Main code source =
.../sklearn2pmml/resources/sklearn2pmml-1.1-SNAPSHOT.jar

However, querying the classloader for:

getResource("META-INF/MANIFEST.MF")

returns the Dynatrace agent manifest first:

FIRST MANIFEST =
.../dynatrace/.../oneagentjava.17.jar!/META-INF/MANIFEST.MF

Build-Timestamp = null
Implementation-Title = oneagentjava.17

Enumerating the visible manifests shows:

#0 oneagentjava.17.jar
#1 oneagentjava.11.jar
#2 oneagentjava.8.jar
#3 oneagentjava.jar
#4 sklearn2pmml-1.1-SNAPSHOT.jar

The actual SkLearn2PMML manifest at index #4 contains:

Build-Timestamp = 2026-06-30T18:45:00Z
Implementation-Title = SkLearn2PMML package
Implementation-Version = 0.132.0

Therefore, the package build timestamp validation appears to depend on whichever generic META-INF/MANIFEST.MF resource is returned first by the classloader, instead of the manifest belonging specifically to the JAR containing com.sklearn2pmml.Main.

Why disabling the Java agent is not a practical workaround

This is an enterprise-managed OpenShift environment.

Dynatrace OneAgent is injected at the host/container level and application users are not permitted to disable enterprise monitoring or modify the host-level instrumentation configuration.

Removing Dynatrace-related environment variables from the Java child process does not change the behavior.

Expected behavior

The build timestamp should be resolved from the artifact containing com.sklearn2pmml.Main, independently of other Java agents or libraries exposing their own META-INF/MANIFEST.MF resources.

For example, the code source of Main.class could be resolved first and the manifest could then be read directly from that JAR, rather than relying on the first generic manifest returned by the classloader.

Minimal diagnostic reproducer

The behavior can be demonstrated without loading a Python estimator:

Class<?> mainClass =
    Class.forName("com.sklearn2pmml.Main");

System.out.println(
    mainClass
        .getProtectionDomain()
        .getCodeSource()
        .getLocation()
);

System.out.println(
    mainClass
        .getClassLoader()
        .getResource("META-INF/MANIFEST.MF")
);

Observed:

Main code source =
.../sklearn2pmml-1.1-SNAPSHOT.jar

META-INF/MANIFEST.MF =
.../oneagentjava.17.jar!/META-INF/MANIFEST.MF

Verified workaround

I was able to work around the issue without disabling Dynatrace and without modifying the SkLearn2PMML JAR.

The workaround launches com.sklearn2pmml.Main through an isolated URLClassLoader and makes META-INF/MANIFEST.MF resolution deterministic by returning the manifest belonging specifically to the SkLearn2PMML JAR.

With this change:

Manifest seen by Main =
.../sklearn2pmml-1.1-SNAPSHOT.jar!/META-INF/MANIFEST.MF

Build-Timestamp =
2026-06-30T18:45:00Z

and the exact same PMML conversion that previously failed completes successfully.

No estimator, Python dependency, Java version, SkLearn2PMML JAR, or Dynatrace configuration needed to be changed.

This appears to further confirm that the issue is specifically caused by generic manifest resource resolution rather than an invalid or undated SkLearn2PMML artifact.

Would it be possible to change the build timestamp lookup so that the manifest associated specifically with the SkLearn2PMML code source is used?

I can provide additional classloader diagnostics or a simplified version of the workaround if useful.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions