-
Type:
Bug
-
Resolution: Unresolved
-
Priority:
Minor
-
Component/s: flaky-test-handler-plugin
-
None
-
Environment:OS: Linux - 6.12.66-88.122.amzn2023.x86_64
Java: 21.0.11 - Eclipse Adoptium (OpenJDK 64-Bit Server VM)
ansicolor:536.v13fa_b_860c267
ant:520.vd082ecfb_16a_9
antisamy-markup-formatter:173.v680e3a_b_69ff3
apache-httpcomponents-client-4-api:4.5.14-269.vfa_2321039a_83
apache-httpcomponents-client-5-api:5.6.2-199.vc3c04d033fcc
asm-api:9.10.1-216.va_9256d3b_844b_
authentication-tokens:1.144.v5ff4a_5ec5c33
badge:3.591.v9074c6c6f0b_9
basic-branch-build-strategies:317.v85b_331d6cc42
bootstrap5-api:5.3.8-1048.va_c299057e35c
bouncycastle-api:2.30.1.84-291.v9f17b_21896e2
branch-api:2.1280.v0d4e5b_b_460ef
build-name-setter:2.5.1
build-timeout:1.40
build-user-vars-plugin:214.va_eed2ed849ca_
caffeine-api:3.2.4-208.v7e2da_a_7db_82b_
checks-api:415.vf022234a_931d
cloud-stats:423.v63f017a_f582c
cloudbees-folder:6.1100.ve9eed61d16c4
command-launcher:134.v025a_5fcf9dea_
commons-compress-api:1.28.0-82.v4df6c060eb_66
commons-httpclient3-api:3.1-3
commons-lang3-api:3.20.0-109.ve43756e2d2b_4
commons-text-api:1.15.0-218.va_61573470393
conditional-buildstep:1.5.0
config-file-provider:1013.v73c323e52b_1f
configuration-as-code:2095.vef6db_3a_b_5b_9c
credentials:1506.v948b_b_b_7dec44
credentials-binding:725.ve52b_2328a_fde
data-tables-api:2.3.8-1570.v1cb_1cd2a_0fb_c
datadog:9.2.0
display-url-api:2.217.va_6b_de84cc74b_
docker-commons:472.vee120e23d3a_c
docker-java-api:3.7.1-136.v5d70f77a_c3d6
docker-plugin:1316.v75635a_002b_0a_
durable-task:671.v340ff7959010
echarts-api:6.0.0-1287.vfd24c22a_3d00
eddsa-api:0.3.0.1-29.v67e9a_1c969b_b_
editable-choice:71.v02a291ebbe45
email-ext:2038.v7b_8817a_499d9
emoji-symbols-api:17.0-57.v8d44b_9a_b_d5ea_
envinject:2.941.v351a_20c0a_3ca_
envinject-api:1.241.vdd714803b_403
extensible-choice-parameter:255.vfa_41f46828ef
external-monitor-job:223.vb_fddcf42c9b_3
extra-columns:1.28
flaky-test-handler:1.3.172.v35b_30de7fa_5b_
font-awesome-api:7.2.0-990.vf220b_2a_496f9
git:5.10.1
git-client:6.6.1
git-server:137.ve0060b_432302
github:1.47.0
github-api:1.330-492.v3941a_032db_2a_
google-oauth-plugin:1.346.v712b_a_e0d1e60
groovy-postbuild:303.v5fe3da_6233f0
gson-api:2.14.0-201.v8eefe5515533
htmlpublisher:427.1
instance-identity:203.v15e81a_1b_7a_38
ionicons-api:94.vcc3065403257
jackson-annotations2-api:2.22-19.v10a_a_582ea_26e
jackson2-api:2.22.0-439.vb_b_43658d6176
jackson3-api:3.2.0-89.v014d02108ea_7
jakarta-activation-api:2.1.4-1
jakarta-mail-api:2.1.5-1
jakarta-xml-bind-api:4.0.9-19.v2b_a_5b_44d9a_1c
javadoc:354.vee1a_660b_4990
javax-activation-api:1.2.0-8
javax-mail-api:1.6.2-11
jaxb:2.3.9-143.v5979df3304e6
jdk-tool:83.v417146707a_3d
jnr-posix-api:3.2.1-213.v7401d99f6220
job-dsl:3654.vdf58f53e2d15
joda-time-api:2.14.2-193.v422b_efce56e0
jquery:1.12.4-3
jquery3-api:3.7.1-687.v68d468e40b_30
jsch:0.2.16-95.v3eecb_55fa_b_78
json-api:20260522-217.v0b_18b_8cd4672
json-path-api:3.0.0-218.vcd4dd1355de2
jsoup:1.22.2-95.vc5d00f1eb_42d
junit:1403.vd9d1413fd205
kubernetes:4423.vb_59f230b_ce53
kubernetes-client-api:7.3.1-256.v788a_0b_787114
kubernetes-credentials:207.v492f58828b_ed
ldap:807.809.vd3a_4e5e4ec98
lockable-resources:1537.v68d014129e68
log-parser:3.0.3
mailer:534.v1b_36f5864073
mapdb-api:1.0.9-44.va_1e1310c9118
matrix-auth:3.2.10
matrix-project:870.v9db_fcfc2f45b_
maven-plugin:3.27
metrics:4.2.37-494.v06f9a_939d33a_
mina-sshd-api-common:2.17.1-187.v0341274c2905
mina-sshd-api-core:2.17.1-187.v0341274c2905
miniorange-saml-sp:3.6.0
monitoring:2.8.0
nested-view:241.v178f0b_a_cd76a_
oauth-credentials:0.660.vce7c108f1f3a_
okhttp-api:5.3.2-200.vedb_720a_cf1f8
oss-symbols-api:465.v25d9fdc88c26
pam-auth:1.12
parameter-separator:334.v1fc0e534c71d
parameterized-trigger:893.va_383a_9b_a_4c11
pipeline-build-step:584.vdb_a_2cc3a_d07a_
pipeline-github-lib:65.v203688e7727e
pipeline-graph-analysis:254.v0f63a_a_447dca_
pipeline-groovy-lib:798.v5cc688825312
pipeline-input-step:560.v56198a_642157
pipeline-milestone-step:152.v6e22b_8cfc66c
pipeline-model-api:2.2291.v2934911987b_6
pipeline-model-definition:2.2291.v2934911987b_6
pipeline-model-extensions:2.2291.v2934911987b_6
pipeline-rest-api:2.41
pipeline-stage-step:345.va_96187909426
pipeline-stage-tags-metadata:2.2291.v2934911987b_6
pipeline-stage-view:2.41
plain-credentials:199.v9f8e1f741799
plugin-util-api:7.1341.v039f146993d9
postbuildscript:3.4.1-695.vf6b_0b_8053979
prism-api:1.30.0-741.v034eb_0b_0a_a_fa_
pubsub-light:1.19
rebuild:338.va_0a_b_50e29397
resource-disposer:0.25
role-strategy:878.v6f1d3b_3a_0769
run-condition:276.v97298f3a_cd51
scm-api:728.vc30dcf7a_0df5
script-security:1402.1405.vc96e74964250
scriptler:462.vdc882580c93c
sectioned-view:1.32
skip-certificate-check:50.vcfa_cdb_b_27312
snakeyaml-api:2.5-149.v72471e9c6371
snakeyaml-engine-api:3.0.1-5.vd98ea_ff3b_92e
sonar:2.18.3
sse-gateway:1.29
ssh-credentials:372.va_250881b_08cd
ssh-slaves:3.1097.v868116049892
sshd:3.384.vc89b_5e138cf9
structs:362.va_b_695ef4fdf9
subversion:1303.vcfd9679fb_c12
timestamper:1.30
token-macro:477.vd4f0dc3cb_cf1
trilead-api:2.284.v1974ea_324382
uno-choice:2.8.9
variant:70.va_d9f17f859e0
woodstox-core-api:7.2.1-6.v3718a_a_11f5c4
workflow-aggregator:608.v67378e9d3db_1
workflow-api:1413.v2ff1a_5e720fa_
workflow-basic-steps:1098.v808b_fd7f8cf4
workflow-cps:4350.vcc65d4958821
workflow-durable-task-step:1479.v56e587f413a_7
workflow-job:1581.ve4b_d0db_fcb_b_b_
workflow-multibranch:821.vc3b_4ea_780798
workflow-scm-step:466.va_d69e602552b_
workflow-step-api:724.v538c2362b_dfb_
workflow-support:1015.v785e5a_b_b_8b_22
ws-cleanup:0.49
OS: Linux - 6.12.66-88.122.amzn2023.x86_64 Java: 21.0.11 - Eclipse Adoptium (OpenJDK 64-Bit Server VM) ansicolor:536.v13fa_b_860c267 ant:520.vd082ecfb_16a_9 antisamy-markup-formatter:173.v680e3a_b_69ff3 apache-httpcomponents-client-4-api:4.5.14-269.vfa_2321039a_83 apache-httpcomponents-client-5-api:5.6.2-199.vc3c04d033fcc asm-api:9.10.1-216.va_9256d3b_844b_ authentication-tokens:1.144.v5ff4a_5ec5c33 badge:3.591.v9074c6c6f0b_9 basic-branch-build-strategies:317.v85b_331d6cc42 bootstrap5-api:5.3.8-1048.va_c299057e35c bouncycastle-api:2.30.1.84-291.v9f17b_21896e2 branch-api:2.1280.v0d4e5b_b_460ef build-name-setter:2.5.1 build-timeout:1.40 build-user-vars-plugin:214.va_eed2ed849ca_ caffeine-api:3.2.4-208.v7e2da_a_7db_82b_ checks-api:415.vf022234a_931d cloud-stats:423.v63f017a_f582c cloudbees-folder:6.1100.ve9eed61d16c4 command-launcher:134.v025a_5fcf9dea_ commons-compress-api:1.28.0-82.v4df6c060eb_66 commons-httpclient3-api:3.1-3 commons-lang3-api:3.20.0-109.ve43756e2d2b_4 commons-text-api:1.15.0-218.va_61573470393 conditional-buildstep:1.5.0 config-file-provider:1013.v73c323e52b_1f configuration-as-code:2095.vef6db_3a_b_5b_9c credentials:1506.v948b_b_b_7dec44 credentials-binding:725.ve52b_2328a_fde data-tables-api:2.3.8-1570.v1cb_1cd2a_0fb_c datadog:9.2.0 display-url-api:2.217.va_6b_de84cc74b_ docker-commons:472.vee120e23d3a_c docker-java-api:3.7.1-136.v5d70f77a_c3d6 docker-plugin:1316.v75635a_002b_0a_ durable-task:671.v340ff7959010 echarts-api:6.0.0-1287.vfd24c22a_3d00 eddsa-api:0.3.0.1-29.v67e9a_1c969b_b_ editable-choice:71.v02a291ebbe45 email-ext:2038.v7b_8817a_499d9 emoji-symbols-api:17.0-57.v8d44b_9a_b_d5ea_ envinject:2.941.v351a_20c0a_3ca_ envinject-api:1.241.vdd714803b_403 extensible-choice-parameter:255.vfa_41f46828ef external-monitor-job:223.vb_fddcf42c9b_3 extra-columns:1.28 flaky-test-handler:1.3.172.v35b_30de7fa_5b_ font-awesome-api:7.2.0-990.vf220b_2a_496f9 git:5.10.1 git-client:6.6.1 git-server:137.ve0060b_432302 github:1.47.0 github-api:1.330-492.v3941a_032db_2a_ google-oauth-plugin:1.346.v712b_a_e0d1e60 groovy-postbuild:303.v5fe3da_6233f0 gson-api:2.14.0-201.v8eefe5515533 htmlpublisher:427.1 instance-identity:203.v15e81a_1b_7a_38 ionicons-api:94.vcc3065403257 jackson-annotations2-api:2.22-19.v10a_a_582ea_26e jackson2-api:2.22.0-439.vb_b_43658d6176 jackson3-api:3.2.0-89.v014d02108ea_7 jakarta-activation-api:2.1.4-1 jakarta-mail-api:2.1.5-1 jakarta-xml-bind-api:4.0.9-19.v2b_a_5b_44d9a_1c javadoc:354.vee1a_660b_4990 javax-activation-api:1.2.0-8 javax-mail-api:1.6.2-11 jaxb:2.3.9-143.v5979df3304e6 jdk-tool:83.v417146707a_3d jnr-posix-api:3.2.1-213.v7401d99f6220 job-dsl:3654.vdf58f53e2d15 joda-time-api:2.14.2-193.v422b_efce56e0 jquery:1.12.4-3 jquery3-api:3.7.1-687.v68d468e40b_30 jsch:0.2.16-95.v3eecb_55fa_b_78 json-api:20260522-217.v0b_18b_8cd4672 json-path-api:3.0.0-218.vcd4dd1355de2 jsoup:1.22.2-95.vc5d00f1eb_42d junit:1403.vd9d1413fd205 kubernetes:4423.vb_59f230b_ce53 kubernetes-client-api:7.3.1-256.v788a_0b_787114 kubernetes-credentials:207.v492f58828b_ed ldap:807.809.vd3a_4e5e4ec98 lockable-resources:1537.v68d014129e68 log-parser:3.0.3 mailer:534.v1b_36f5864073 mapdb-api:1.0.9-44.va_1e1310c9118 matrix-auth:3.2.10 matrix-project:870.v9db_fcfc2f45b_ maven-plugin:3.27 metrics:4.2.37-494.v06f9a_939d33a_ mina-sshd-api-common:2.17.1-187.v0341274c2905 mina-sshd-api-core:2.17.1-187.v0341274c2905 miniorange-saml-sp:3.6.0 monitoring:2.8.0 nested-view:241.v178f0b_a_cd76a_ oauth-credentials:0.660.vce7c108f1f3a_ okhttp-api:5.3.2-200.vedb_720a_cf1f8 oss-symbols-api:465.v25d9fdc88c26 pam-auth:1.12 parameter-separator:334.v1fc0e534c71d parameterized-trigger:893.va_383a_9b_a_4c11 pipeline-build-step:584.vdb_a_2cc3a_d07a_ pipeline-github-lib:65.v203688e7727e pipeline-graph-analysis:254.v0f63a_a_447dca_ pipeline-groovy-lib:798.v5cc688825312 pipeline-input-step:560.v56198a_642157 pipeline-milestone-step:152.v6e22b_8cfc66c pipeline-model-api:2.2291.v2934911987b_6 pipeline-model-definition:2.2291.v2934911987b_6 pipeline-model-extensions:2.2291.v2934911987b_6 pipeline-rest-api:2.41 pipeline-stage-step:345.va_96187909426 pipeline-stage-tags-metadata:2.2291.v2934911987b_6 pipeline-stage-view:2.41 plain-credentials:199.v9f8e1f741799 plugin-util-api:7.1341.v039f146993d9 postbuildscript:3.4.1-695.vf6b_0b_8053979 prism-api:1.30.0-741.v034eb_0b_0a_a_fa_ pubsub-light:1.19 rebuild:338.va_0a_b_50e29397 resource-disposer:0.25 role-strategy:878.v6f1d3b_3a_0769 run-condition:276.v97298f3a_cd51 scm-api:728.vc30dcf7a_0df5 script-security:1402.1405.vc96e74964250 scriptler:462.vdc882580c93c sectioned-view:1.32 skip-certificate-check:50.vcfa_cdb_b_27312 snakeyaml-api:2.5-149.v72471e9c6371 snakeyaml-engine-api:3.0.1-5.vd98ea_ff3b_92e sonar:2.18.3 sse-gateway:1.29 ssh-credentials:372.va_250881b_08cd ssh-slaves:3.1097.v868116049892 sshd:3.384.vc89b_5e138cf9 structs:362.va_b_695ef4fdf9 subversion:1303.vcfd9679fb_c12 timestamper:1.30 token-macro:477.vd4f0dc3cb_cf1 trilead-api:2.284.v1974ea_324382 uno-choice:2.8.9 variant:70.va_d9f17f859e0 woodstox-core-api:7.2.1-6.v3718a_a_11f5c4 workflow-aggregator:608.v67378e9d3db_1 workflow-api:1413.v2ff1a_5e720fa_ workflow-basic-steps:1098.v808b_fd7f8cf4 workflow-cps:4350.vcc65d4958821 workflow-durable-task-step:1479.v56e587f413a_7 workflow-job:1581.ve4b_d0db_fcb_b_b_ workflow-multibranch:821.vc3b_4ea_780798 workflow-scm-step:466.va_d69e602552b_ workflow-step-api:724.v538c2362b_dfb_ workflow-support:1015.v785e5a_b_b_8b_22 ws-cleanup:0.49
Copied from https://github.com/jenkinsci/jenkins/issues/27168 with special thanks to https://github.com/byn-beno-zurman
Reproduction steps
- Create a JUnit 5 test that fails ~50% of the time:
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; class RandomlyFailingTest { @Test void randomlyFails() { double value = Math.random(); System.out.println("chosen value: " + value); assertTrue(value > 0.5); } }
- Enable in-build retries in Maven Surefire:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <rerunFailingTestsCount>10</rerunFailingTestsCount> </configuration> </plugin>
With 10 retries the test ends flaky (fail → pass) in ~50% of builds, passes clean in ~50%, and fails all attempts in ~0.05% — so a handful of builds produces both affected and unaffected records.
- Create a freestyle job:
- Build step: mvn test (or any Maven/shell step running the module)
- Post-build action: Publish JUnit test result report, pattern **/target/surefire-reports/**/*.xml
- Additional test report features: Publish JUnit flaky stats (JUnitFlakyTestDataPublisher)
- (Optional, matches our setup: also add the top-level Publish JUnit flaky test reports / JUnitFlakyResultArchiver — not required to reproduce.)
- Run ~10 builds. Note which builds retried the test — visible in the console log:
[ERROR] Run 1: RandomlyFailingTest.randomlyFails:12 expected: <true> but was: <false> [INFO] Run 2: PASS
or via <build>/testReport/.../randomlyFails/api/json → non-empty flakyFailures (retried, then passed) or rerunFailures (failed all attempts). Builds where value > 0.5 on the first attempt have neither.
At this point all builds display correctly in the UI — the Run objects are still in controller memory. On disk, however, each build with a retried test has a multi-MB build.xml, versus a few hundred KB without the flaky publisher.
- Force a lazy reload of the build records. Either:
- edit the job config and save (a no-op change suffices; a Job DSL seed-job re-run also triggers it), or
- restart Jenkins.
- Query build metadata:
GET <job>/api/json?tree=builds[number,result,timestamp,duration]
A Jenkins core maintainer independently built and confirmed a standalone repro using these same steps — see the attached gh-core-27009.zip on jenkinsci/jenkins#27009, a self-contained Docker/Configuration-as-Code setup that deterministically reproduces the corruption after a restart.
Expected Results
Every build in which the test was retried at least once (flaky pass, or failed all retry attempts) should reload from build.xml with its correct result, timestamp, and duration — the same values shown immediately after the build ran and the same values recorded in the on-disk build.xml, which is well-formed and semantically complete (verified with a SAX parser; the true result is also visible at the end of the build's console log, e.g. Finished: UNSTABLE).
Actual Results
Every build in which the test was retried at least once now returns:
{"number": N, "result": "ABORTED", "timestamp": 0, "duration": 0}
and renders in the UI as ABORTED, "Started 56 yr ago", "Took 0 ms". Builds where the test passed on the first attempt (no retry) reload correctly. In an 11-build test run, the split was exact: 3 builds with no retry loaded fine, 8 builds that retried the test were broken.
This is a read-side deserialization failure, not write-time corruption. JUnitFlakyTestDataPublisher.contributeTestData() re-parses all surefire XML reports from disk independently of the main JUnit result parsing (see the FlakyTestResult(TestResult) constructor, which takes only file paths from the JUnit result and re-parses them itself), and serializes this into TestResultAction's <testData> element in build.xml. For any build with a retried test, the resulting build.xml ends up serializing every suite twice, in two different shapes: once as the plugin's independently re-parsed copy, and once as a plain hudson.tasks.junit.SuiteResult/CaseResult graph reachable via object references from the rerun/flaky entries (FlakyCaseResult → <parent>). Same underlying file, two entries, different computed durations.
On the next XStream load, RobustReflectionConverter fails on this graph. One observed manifestation is an explicit ConversionException from XStream2$BlacklistedTypesConverter refusing to unmarshal java.util.Map$Entry inside testCaseFlakyInfoMap (a JEP-200 class-filtering rejection, since java.util.Map$Entry has no codebase location and isn't in the default whitelist):
com.thoughtworks.xstream.converters.ConversionException: Refusing to unmarshal entry for security reasons; see https://www.jenkins.io/redirect/class-filter/ ---- Debugging information ---- message : Refusing to unmarshal entry for security reasons; see https://www.jenkins.io/redirect/class-filter/ class : java.util.Map$Entry required-type : java.util.Map$Entry converter-type : hudson.util.XStream2$BlacklistedTypesConverter path : /build/actions/hudson.tasks.junit.TestResultAction/testData/com.google.jenkins.flakyTestHandler.plugin.JUnitFlakyTestData/testCaseFlakyInfoMap/entry[9749]
Either way, the load silently drops critical Run fields and the record becomes the <broken data JENKINS-45892> placeholder. Loading the file manually via Run.XSTREAM2.fromXML(buildXml) reproduces the failure deterministically, confirming the on-disk data is intact but the object graph is unreconstructable — so an in-memory patch/repair script cannot help once a build has already been reloaded once, and the correct values cannot be recovered.
Affected builds never appear in the Old Data Monitor, so there is no built-in way to detect which historical builds are affected.
Build/test duration and suite size are not the trigger. A sub-second flaky test in a 2-6 minute build reproduces the corruption on every build where it retries, while much larger builds (~10 hours, ~9,500 tests) are unaffected as long as no test in them was retried. The only variable that matters is whether a retried test's data was embedded in the build. Builds appear to display correctly for a while after they run only because the in-memory Run object hasn't yet been evicted/reloaded — the first lazy reload (config save, seed job rerun, or restart) is what exposes the bug.
Anything else?
Originally filed against Jenkins core as jenkinsci/jenkins#27009. Root cause was narrowed down there with help from core maintainers, who confirmed the issue is specific to this plugin's testData serialization rather than core, and asked that it be reported here.
Verified workaround (not a fix): removing JUnitFlakyTestDataPublisher while keeping JUnitFlakyResultArchiver resolves it completely. In our Job DSL:
testDataPublishers {
publishFlakyTestsReport()
}
— removing just this block (keeping jUnitFlakyResultArchiver()) dropped build.xml size from 12 MB to 8.2 KB on our smaller suite, and confirmed a forced cache purge + reload loads the record correctly. The job-level Flaky History table (historyAggregate, fed by JUnitFlakyResultArchiver's separate junitFlakyStatsResult.xml) keeps working; only the per-case rerun detail in individual build test reports is lost. Confirmed at production scale: after removing this from three branches' freestyle Job DSL, overnight ~10-hour, ~9,500-test builds have produced 9.8-12.7 KB build.xml files that survive reload without issue, and no new broken builds have occurred since.
Given how common rerunFailingTestsCount-style retries are in Maven Surefire configs, this likely affects many installations using JUnitFlakyTestDataPublisher, with no visibility into the damage until someone goes looking at a specific build's history.
Are you interested in contributing a fix?
I don't think I'm capable to do this...