This is an automated email from the ASF dual-hosted git repository.

bamaer pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/main by this push:
     new 9e94fa7411 Issue #9039 : Read Neo4j execution dates stored by graph 
logging (#9044)
9e94fa7411 is described below

commit 9e94fa74117db5d7e664f5b7f4bb14c20dc666b3
Author: Matt Casters <[email protected]>
AuthorDate: Tue Oct 20 20:34:19 2026 +0200

    Issue #9039 : Read Neo4j execution dates stored by graph logging (#9044)
    
    Graph logging writes registration dates as yyyy/MM/dd'T'HH:mm:ss. The 
execution information location only parsed ISO local date-times, so one such 
value aborted the whole execution list. Parse the logging format, ISO strings, 
and offset values, skip a node that still cannot be read, and clear the static 
location cache when the location closes.
    
    An integration test writes a workflow and pipeline with logging enabled and 
reads the dates, parent link, and sample rows back through the location.
---
 .../main-neo4j-execution-info-roundtrip.hwf        |  217 ++++
 .../roundtrip-check.hpl                            | 1190 ++++++++++++++++++++
 .../subject-pipeline.hpl                           |  114 ++
 .../subject-workflow.hwf                           |   93 ++
 .../neo4j/execution/NeoExecutionInfoLocation.java  |  128 ++-
 .../apache/hop/neo4j/logging/util/LoggingCore.java |   63 +-
 .../NeoExecutionInfoLocationReadTest.java          |  112 ++
 .../hop/neo4j/logging/util/LoggingCoreTest.java    |   24 +-
 8 files changed, 1908 insertions(+), 33 deletions(-)

diff --git 
a/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/main-neo4j-execution-info-roundtrip.hwf
 
b/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/main-neo4j-execution-info-roundtrip.hwf
new file mode 100644
index 0000000000..47afb8da3e
--- /dev/null
+++ 
b/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/main-neo4j-execution-info-roundtrip.hwf
@@ -0,0 +1,217 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<workflow>
+  <name>main-neo4j-execution-info-roundtrip</name>
+  <name_sync_with_filename>Y</name_sync_with_filename>
+  <description>Writes a workflow and a pipeline to the Neo4j execution 
information location while graph logging is on, then reads them back. See issue 
#9039.</description>
+  <extended_description>Graph logging stores executionStart as 
yyyy/MM/dd'T'HH:mm:ss. The check copies that text onto the pipeline 
registrationDate and the same instant as an ISO string onto the workflow, then 
reads both back through the execution information 
location.</extended_description>
+  <workflow_version/>
+  <created_user>-</created_user>
+  <created_date>2026/10/20 14:00:00.000</created_date>
+  <modified_user>-</modified_user>
+  <modified_date>2026/10/20 14:00:00.000</modified_date>
+  <parameters>
+  </parameters>
+  <actions>
+    <action>
+      <name>Start</name>
+      <description/>
+      <type>SPECIAL</type>
+      <attributes/>
+      <repeat>N</repeat>
+      <schedulerType>0</schedulerType>
+      <intervalSeconds>0</intervalSeconds>
+      <intervalMinutes>60</intervalMinutes>
+      <hour>12</hour>
+      <minutes>0</minutes>
+      <weekDay>1</weekDay>
+      <DayOfMonth>1</DayOfMonth>
+      <parallel>N</parallel>
+      <xloc>80</xloc>
+      <yloc>128</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>cleanup-database.hwf</name>
+      <description/>
+      <type>WORKFLOW</type>
+      <attributes/>
+      <filename>${PROJECT_HOME}/tests/shared/cleanup-database.hwf</filename>
+      <params_from_previous>N</params_from_previous>
+      <exec_per_row>N</exec_per_row>
+      <set_logfile>N</set_logfile>
+      <logfile/>
+      <logext/>
+      <add_date>N</add_date>
+      <add_time>N</add_time>
+      <loglevel>Nothing</loglevel>
+      <wait_until_finished>Y</wait_until_finished>
+      <follow_abort_remote>N</follow_abort_remote>
+      <create_parent_folder>N</create_parent_folder>
+      <pass_export>N</pass_export>
+      <run_configuration>local</run_configuration>
+      <parameters>
+        <pass_all_parameters>Y</pass_all_parameters>
+      </parameters>
+      <set_append_logfile>N</set_append_logfile>
+      <parallel>N</parallel>
+      <xloc>240</xloc>
+      <yloc>128</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>enable logging</name>
+      <description/>
+      <type>SET_VARIABLES</type>
+      <attributes/>
+      <replacevars>Y</replacevars>
+      <filename/>
+      <file_variable_type>CURRENT_WORKFLOW</file_variable_type>
+      <fields>
+        <field>
+          <variable_name>HOP_GRAPH_LOGGING_CONNECTION</variable_name>
+          <variable_value>Test</variable_value>
+          <variable_type>CURRENT_WORKFLOW</variable_type>
+        </field>
+      </fields>
+      <parallel>N</parallel>
+      <xloc>416</xloc>
+      <yloc>128</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>subject-workflow.hwf</name>
+      <description/>
+      <type>WORKFLOW</type>
+      <attributes/>
+      
<filename>${PROJECT_HOME}/tests/neo4j-execution-info-roundtrip/subject-workflow.hwf</filename>
+      <params_from_previous>N</params_from_previous>
+      <exec_per_row>N</exec_per_row>
+      <set_logfile>N</set_logfile>
+      <logfile/>
+      <logext/>
+      <add_date>N</add_date>
+      <add_time>N</add_time>
+      <loglevel>Basic</loglevel>
+      <wait_until_finished>Y</wait_until_finished>
+      <follow_abort_remote>N</follow_abort_remote>
+      <create_parent_folder>N</create_parent_folder>
+      <pass_export>N</pass_export>
+      <run_configuration>local-neo4j</run_configuration>
+      <parameters>
+        <pass_all_parameters>Y</pass_all_parameters>
+      </parameters>
+      <set_append_logfile>N</set_append_logfile>
+      <parallel>N</parallel>
+      <xloc>608</xloc>
+      <yloc>128</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>disable logging</name>
+      <description/>
+      <type>SET_VARIABLES</type>
+      <attributes/>
+      <replacevars>Y</replacevars>
+      <filename/>
+      <file_variable_type>CURRENT_WORKFLOW</file_variable_type>
+      <fields>
+        <field>
+          <variable_name>HOP_GRAPH_LOGGING_CONNECTION</variable_name>
+          <variable_value>-</variable_value>
+          <variable_type>CURRENT_WORKFLOW</variable_type>
+        </field>
+      </fields>
+      <parallel>N</parallel>
+      <xloc>800</xloc>
+      <yloc>128</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>roundtrip-check.hpl</name>
+      <description/>
+      <type>PIPELINE</type>
+      <attributes/>
+      
<filename>${PROJECT_HOME}/tests/neo4j-execution-info-roundtrip/roundtrip-check.hpl</filename>
+      <params_from_previous>N</params_from_previous>
+      <exec_per_row>N</exec_per_row>
+      <clear_rows>N</clear_rows>
+      <clear_files>N</clear_files>
+      <set_logfile>N</set_logfile>
+      <logfile/>
+      <logext/>
+      <add_date>N</add_date>
+      <add_time>N</add_time>
+      <loglevel>Basic</loglevel>
+      <set_append_logfile>N</set_append_logfile>
+      <wait_until_finished>Y</wait_until_finished>
+      <follow_abort_remote>N</follow_abort_remote>
+      <create_parent_folder>N</create_parent_folder>
+      <run_configuration>local</run_configuration>
+      <parameters>
+        <pass_all_parameters>Y</pass_all_parameters>
+      </parameters>
+      <parallel>N</parallel>
+      <xloc>992</xloc>
+      <yloc>128</yloc>
+      <attributes_hac/>
+    </action>
+  </actions>
+  <hops>
+    <hop>
+      <from>Start</from>
+      <to>cleanup-database.hwf</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>Y</unconditional>
+    </hop>
+    <hop>
+      <from>cleanup-database.hwf</from>
+      <to>enable logging</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>enable logging</from>
+      <to>subject-workflow.hwf</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>subject-workflow.hwf</from>
+      <to>disable logging</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+    <hop>
+      <from>disable logging</from>
+      <to>roundtrip-check.hpl</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>N</unconditional>
+    </hop>
+  </hops>
+  <notepads>
+  </notepads>
+  <attributes/>
+</workflow>
diff --git 
a/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/roundtrip-check.hpl
 
b/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/roundtrip-check.hpl
new file mode 100644
index 0000000000..3b5af4dd48
--- /dev/null
+++ 
b/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/roundtrip-check.hpl
@@ -0,0 +1,1190 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<pipeline>
+  <info>
+    <name>roundtrip-check</name>
+    <name_sync_with_filename>Y</name_sync_with_filename>
+    <description>Reads the subject workflow and pipeline back from the Neo4j 
execution information location, including a logging-format registration date. 
See issue #9039.</description>
+    <extended_description/>
+    <pipeline_version/>
+    <pipeline_type>Normal</pipeline_type>
+    <parameters>
+    </parameters>
+    <capture_transform_performance>N</capture_transform_performance>
+    
<transform_performance_capturing_delay>1000</transform_performance_capturing_delay>
+    
<transform_performance_capturing_size_limit>100</transform_performance_capturing_size_limit>
+    <created_user>-</created_user>
+    <created_date>2026/10/20 14:00:00.000</created_date>
+    <modified_user>-</modified_user>
+    <modified_date>2026/10/20 14:00:00.000</modified_date>
+  </info>
+  <notepads>
+  </notepads>
+  <order>
+    <hop>
+      <from>names</from>
+      <to>count logging dates</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>count logging dates</from>
+      <to>logging dates present</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>logging dates present</from>
+      <to>set pipeline date</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>logging dates present</from>
+      <to>Abort no logging date</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>set pipeline date</from>
+      <to>pipeline updated</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>pipeline updated</from>
+      <to>set workflow date</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>pipeline updated</from>
+      <to>Abort pipeline not stored</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>set workflow date</from>
+      <to>workflow updated</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>workflow updated</from>
+      <to>stringify other dates</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>workflow updated</from>
+      <to>Abort workflow not stored</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>stringify other dates</from>
+      <to>remove typeless</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>remove typeless</from>
+      <to>find pipeline</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>remove typeless</from>
+      <to>find workflow</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>find pipeline</from>
+      <to>missing pipeline</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>find pipeline</from>
+      <to>check pipeline</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>missing pipeline</from>
+      <to>Abort missing pipeline</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>check pipeline</from>
+      <to>find parent</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>check pipeline</from>
+      <to>execution data</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>find parent</from>
+      <to>missing parent</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>find parent</from>
+      <to>check parent</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>missing parent</from>
+      <to>Abort missing parent</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>check parent</from>
+      <to>keep child lookup fields</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>keep child lookup fields</from>
+      <to>find children</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>find children</from>
+      <to>child is pipeline</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>child is pipeline</from>
+      <to>child ok</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>child ok</from>
+      <to>no child</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>no child</from>
+      <to>Abort no child</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>execution data</from>
+      <to>rows with marker</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>rows with marker</from>
+      <to>samples ok</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>samples ok</from>
+      <to>no samples</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>no samples</from>
+      <to>Abort no samples</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>find workflow</from>
+      <to>missing workflow</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>find workflow</from>
+      <to>check workflow</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>missing workflow</from>
+      <to>Abort missing workflow</to>
+      <enabled>Y</enabled>
+    </hop>
+  </order>
+  <transform>
+    <name>names</name>
+    <type>DataGrid</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <data>
+      <line>
+        <item>subject-pipeline</item>
+        <item>Pipeline</item>
+        <item>subject-workflow</item>
+        <item>Workflow</item>
+        <item>all-transforms</item>
+      </line>
+    </data>
+    <fields>
+      <field>
+        <name>pipelineName</name>
+        <type>String</type>
+        <length>-1</length>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+      </field>
+      <field>
+        <name>pipelineType</name>
+        <type>String</type>
+        <length>-1</length>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+      </field>
+      <field>
+        <name>workflowName</name>
+        <type>String</type>
+        <length>-1</length>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+      </field>
+      <field>
+        <name>workflowType</name>
+        <type>String</type>
+        <length>-1</length>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+      </field>
+      <field>
+        <name>owner</name>
+        <type>String</type>
+        <length>-1</length>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+      </field>
+    </fields>
+    <attributes/>
+    <GUI>
+      <xloc>80</xloc>
+      <yloc>160</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>count logging dates</name>
+    <type>Neo4jCypherOutput</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <connection>Test</connection>
+    <cypher>MATCH (e:Execution) WHERE e.executionStart IS NOT NULL AND 
valueType(e.executionStart) STARTS WITH 'STRING' RETURN count(e) AS 
loggingDates</cypher>
+    <cypher_from_field>N</cypher_from_field>
+    <read_only>N</read_only>
+    <retry>Y</retry>
+    <returning_graph>N</returning_graph>
+    <unwind>N</unwind>
+    <returns>
+      <return>
+        <name>loggingDates</name>
+        <source_type>Integer</source_type>
+        <type>Integer</type>
+      </return>
+    </returns>
+    <attributes/>
+    <GUI>
+      <xloc>256</xloc>
+      <yloc>160</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>logging dates present</name>
+    <type>FilterRows</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <send_true_to>set pipeline date</send_true_to>
+    <send_false_to>Abort no logging date</send_false_to>
+    <compare>
+      <condition>
+        <negated>N</negated>
+        <leftvalue>loggingDates</leftvalue>
+        <function>&gt;</function>
+        <rightvalue/>
+        <value>
+          <name>constant</name>
+          <type>Integer</type>
+          <text>0</text>
+          <length>-1</length>
+          <precision>-1</precision>
+          <isnull>N</isnull>
+          <mask/>
+        </value>
+      </condition>
+    </compare>
+    <attributes/>
+    <GUI>
+      <xloc>432</xloc>
+      <yloc>160</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Abort no logging date</name>
+    <type>Abort</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <abort_option>ABORT_WITH_ERROR</abort_option>
+    <always_log_rows>Y</always_log_rows>
+    <message>Graph logging did not store an executionStart string</message>
+    <row_threshold>0</row_threshold>
+    <attributes/>
+    <GUI>
+      <xloc>432</xloc>
+      <yloc>304</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>set pipeline date</name>
+    <type>Neo4jCypherOutput</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <connection>Test</connection>
+    <cypher>MATCH (src:Execution {type: 'PIPELINE', name: 'subject-pipeline'}) 
WHERE src.executionStart IS NOT NULL AND valueType(src.executionStart) STARTS 
WITH 'STRING' MATCH (e:Execution {executionType: 'Pipeline', name: 
'subject-pipeline'}) SET e.registrationDate = src.executionStart RETURN 
src.executionStart AS loggedPipelineDate, count(e) AS pipelineNodes</cypher>
+    <cypher_from_field>N</cypher_from_field>
+    <read_only>N</read_only>
+    <retry>Y</retry>
+    <returning_graph>N</returning_graph>
+    <unwind>N</unwind>
+    <returns>
+      <return>
+        <name>loggedPipelineDate</name>
+        <source_type>String</source_type>
+        <type>String</type>
+      </return>
+      <return>
+        <name>pipelineNodes</name>
+        <source_type>Integer</source_type>
+        <type>Integer</type>
+      </return>
+    </returns>
+    <attributes/>
+    <GUI>
+      <xloc>608</xloc>
+      <yloc>160</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>pipeline updated</name>
+    <type>FilterRows</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <send_true_to>set workflow date</send_true_to>
+    <send_false_to>Abort pipeline not stored</send_false_to>
+    <compare>
+      <condition>
+        <negated>N</negated>
+        <leftvalue>pipelineNodes</leftvalue>
+        <function>&gt;</function>
+        <rightvalue/>
+        <value>
+          <name>constant</name>
+          <type>Integer</type>
+          <text>0</text>
+          <length>-1</length>
+          <precision>-1</precision>
+          <isnull>N</isnull>
+          <mask/>
+        </value>
+      </condition>
+    </compare>
+    <attributes/>
+    <GUI>
+      <xloc>784</xloc>
+      <yloc>160</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Abort pipeline not stored</name>
+    <type>Abort</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <abort_option>ABORT_WITH_ERROR</abort_option>
+    <always_log_rows>Y</always_log_rows>
+    <message>The subject pipeline execution was not stored</message>
+    <row_threshold>0</row_threshold>
+    <attributes/>
+    <GUI>
+      <xloc>784</xloc>
+      <yloc>304</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>set workflow date</name>
+    <type>Neo4jCypherOutput</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <connection>Test</connection>
+    <cypher>MATCH (src:Execution {type: 'WORKFLOW', name: 'subject-workflow'}) 
WHERE src.executionStart IS NOT NULL AND valueType(src.executionStart) STARTS 
WITH 'STRING' MATCH (e:Execution {executionType: 'Workflow', name: 
'subject-workflow'}) SET e.registrationDate = replace(src.executionStart, '/', 
'-') RETURN replace(src.executionStart, '/', '-') AS loggedWorkflowDate, 
count(e) AS workflowNodes</cypher>
+    <cypher_from_field>N</cypher_from_field>
+    <read_only>N</read_only>
+    <retry>Y</retry>
+    <returning_graph>N</returning_graph>
+    <unwind>N</unwind>
+    <returns>
+      <return>
+        <name>loggedWorkflowDate</name>
+        <source_type>String</source_type>
+        <type>String</type>
+      </return>
+      <return>
+        <name>workflowNodes</name>
+        <source_type>Integer</source_type>
+        <type>Integer</type>
+      </return>
+    </returns>
+    <attributes/>
+    <GUI>
+      <xloc>960</xloc>
+      <yloc>160</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>workflow updated</name>
+    <type>FilterRows</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <send_true_to>stringify other dates</send_true_to>
+    <send_false_to>Abort workflow not stored</send_false_to>
+    <compare>
+      <condition>
+        <negated>N</negated>
+        <leftvalue>workflowNodes</leftvalue>
+        <function>&gt;</function>
+        <rightvalue/>
+        <value>
+          <name>constant</name>
+          <type>Integer</type>
+          <text>0</text>
+          <length>-1</length>
+          <precision>-1</precision>
+          <isnull>N</isnull>
+          <mask/>
+        </value>
+      </condition>
+    </compare>
+    <attributes/>
+    <GUI>
+      <xloc>1136</xloc>
+      <yloc>160</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Abort workflow not stored</name>
+    <type>Abort</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <abort_option>ABORT_WITH_ERROR</abort_option>
+    <always_log_rows>Y</always_log_rows>
+    <message>The subject workflow execution was not stored</message>
+    <row_threshold>0</row_threshold>
+    <attributes/>
+    <GUI>
+      <xloc>1136</xloc>
+      <yloc>304</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>stringify other dates</name>
+    <type>Neo4jCypherOutput</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <connection>Test</connection>
+    <cypher>MATCH (e:Execution) WHERE e.executionType IS NOT NULL AND 
e.registrationDate IS NOT NULL AND NOT valueType(e.registrationDate) STARTS 
WITH 'STRING' SET e.registrationDate = '2026/10/07T16:08:52' RETURN count(e) AS 
converted</cypher>
+    <cypher_from_field>N</cypher_from_field>
+    <read_only>N</read_only>
+    <retry>Y</retry>
+    <returning_graph>N</returning_graph>
+    <unwind>N</unwind>
+    <returns>
+      <return>
+        <name>converted</name>
+        <source_type>Integer</source_type>
+        <type>Integer</type>
+      </return>
+    </returns>
+    <attributes/>
+    <GUI>
+      <xloc>1312</xloc>
+      <yloc>160</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>remove typeless</name>
+    <type>Neo4jCypherOutput</type>
+    <description/>
+    <distribute>N</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <connection>Test</connection>
+    <cypher>MATCH (e:Execution) WHERE e.executionType IS NULL WITH collect(e) 
AS doomed FOREACH (n IN doomed | DETACH DELETE n) RETURN size(doomed) AS 
removed</cypher>
+    <cypher_from_field>N</cypher_from_field>
+    <read_only>N</read_only>
+    <retry>Y</retry>
+    <returning_graph>N</returning_graph>
+    <unwind>N</unwind>
+    <returns>
+      <return>
+        <name>removed</name>
+        <source_type>Integer</source_type>
+        <type>Integer</type>
+      </return>
+    </returns>
+    <attributes/>
+    <GUI>
+      <xloc>1488</xloc>
+      <yloc>160</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>find pipeline</name>
+    <type>ExecInfo</type>
+    <description/>
+    <distribute>N</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <location>neo4j</location>
+    <operationType>FindLastExecution</operationType>
+    <idFieldName/>
+    <parentIdFieldName/>
+    <typeFieldName>pipelineType</typeFieldName>
+    <nameFieldName>pipelineName</nameFieldName>
+    <includeChildrenFieldName/>
+    <limitFieldName/>
+    <attributes/>
+    <GUI>
+      <xloc>1680</xloc>
+      <yloc>64</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>missing pipeline</name>
+    <type>DetectEmptyStream</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <attributes/>
+    <GUI>
+      <xloc>1856</xloc>
+      <yloc>208</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Abort missing pipeline</name>
+    <type>Abort</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <abort_option>ABORT_WITH_ERROR</abort_option>
+    <always_log_rows>Y</always_log_rows>
+    <message>The location did not return the subject pipeline</message>
+    <row_threshold>0</row_threshold>
+    <attributes/>
+    <GUI>
+      <xloc>2032</xloc>
+      <yloc>208</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>check pipeline</name>
+    <type>ScriptValueMod</type>
+    <description/>
+    <distribute>N</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <optimizationLevel>9</optimizationLevel>
+    <jsScripts>
+      <jsScript>
+        <jsScript_type>0</jsScript_type>
+        <jsScript_name>Script 1</jsScript_name>
+        <jsScript_script><![CDATA[if (registrationDate == null || 
executionStartDate == null || executionEndDate == null || updateTime == null) {
+  throw "Pipeline execution is missing a date";
+}
+if (parentId == null || parentId == "") {
+  throw "Pipeline execution has no parent";
+}
+if (failed == true) {
+  throw "Pipeline execution failed";
+}
+if (statusDescription == null || statusDescription.indexOf("Finished") < 0) {
+  throw "Pipeline status is not finished: " + statusDescription;
+}
+var DateFormat = Packages.java.text.SimpleDateFormat;
+var text = "" + new 
DateFormat("yyyy/MM/dd'T'HH:mm:ss").format(registrationDate);
+var expected = "" + loggedPipelineDate;
+if (text != expected) {
+  throw "Pipeline registrationDate was [" + text + "] expected [" + expected + 
"]";
+}
+]]></jsScript_script>
+      </jsScript>
+    </jsScripts>
+    <fields/>
+    <attributes/>
+    <GUI>
+      <xloc>1856</xloc>
+      <yloc>64</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>find parent</name>
+    <type>ExecInfo</type>
+    <description/>
+    <distribute>N</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <location>neo4j</location>
+    <operationType>FindParentId</operationType>
+    <idFieldName>executionId</idFieldName>
+    <parentIdFieldName/>
+    <typeFieldName/>
+    <nameFieldName/>
+    <includeChildrenFieldName/>
+    <limitFieldName/>
+    <attributes/>
+    <GUI>
+      <xloc>2032</xloc>
+      <yloc>64</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>missing parent</name>
+    <type>DetectEmptyStream</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <attributes/>
+    <GUI>
+      <xloc>2208</xloc>
+      <yloc>208</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Abort missing parent</name>
+    <type>Abort</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <abort_option>ABORT_WITH_ERROR</abort_option>
+    <always_log_rows>Y</always_log_rows>
+    <message>findParentId returned nothing for the subject pipeline</message>
+    <row_threshold>0</row_threshold>
+    <attributes/>
+    <GUI>
+      <xloc>2384</xloc>
+      <yloc>208</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>check parent</name>
+    <type>ScriptValueMod</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <optimizationLevel>9</optimizationLevel>
+    <jsScripts>
+      <jsScript>
+        <jsScript_type>0</jsScript_type>
+        <jsScript_name>Script 1</jsScript_name>
+        <jsScript_script><![CDATA[if (id == null || !id.equals(parentId)) {
+  throw "findParentId [" + id + "] did not match parentId [" + parentId + "]";
+}
+]]></jsScript_script>
+      </jsScript>
+    </jsScripts>
+    <fields/>
+    <attributes/>
+    <GUI>
+      <xloc>2208</xloc>
+      <yloc>64</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>keep child lookup fields</name>
+    <type>SelectValues</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <fields>
+      <field>
+        <name>parentId</name>
+      </field>
+      <field>
+        <name>executionId</name>
+        <rename>pipelineExecutionId</rename>
+      </field>
+      <select_unspecified>N</select_unspecified>
+    </fields>
+    <attributes/>
+    <GUI>
+      <xloc>2384</xloc>
+      <yloc>64</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>find children</name>
+    <type>ExecInfo</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <location>neo4j</location>
+    <operationType>FindExecutions</operationType>
+    <idFieldName/>
+    <parentIdFieldName>parentId</parentIdFieldName>
+    <typeFieldName/>
+    <nameFieldName/>
+    <includeChildrenFieldName/>
+    <limitFieldName/>
+    <attributes/>
+    <GUI>
+      <xloc>2560</xloc>
+      <yloc>64</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>child is pipeline</name>
+    <type>FilterRows</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <send_true_to>child ok</send_true_to>
+    <send_false_to/>
+    <compare>
+      <condition>
+        <negated>N</negated>
+        <leftvalue>name</leftvalue>
+        <function>=</function>
+        <rightvalue/>
+        <value>
+          <name>constant</name>
+          <type>String</type>
+          <text>subject-pipeline</text>
+          <length>-1</length>
+          <precision>-1</precision>
+          <isnull>N</isnull>
+          <mask/>
+        </value>
+      </condition>
+    </compare>
+    <attributes/>
+    <GUI>
+      <xloc>2736</xloc>
+      <yloc>64</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>child ok</name>
+    <type>Dummy</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <attributes/>
+    <GUI>
+      <xloc>2912</xloc>
+      <yloc>64</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>no child</name>
+    <type>DetectEmptyStream</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <attributes/>
+    <GUI>
+      <xloc>2912</xloc>
+      <yloc>208</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Abort no child</name>
+    <type>Abort</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <abort_option>ABORT_WITH_ERROR</abort_option>
+    <always_log_rows>Y</always_log_rows>
+    <message>findExecutions did not return the subject pipeline</message>
+    <row_threshold>0</row_threshold>
+    <attributes/>
+    <GUI>
+      <xloc>3088</xloc>
+      <yloc>208</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>execution data</name>
+    <type>ExecInfo</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <location>neo4j</location>
+    <operationType>GetExecutionData</operationType>
+    <idFieldName>owner</idFieldName>
+    <parentIdFieldName>executionId</parentIdFieldName>
+    <typeFieldName/>
+    <nameFieldName/>
+    <includeChildrenFieldName/>
+    <limitFieldName/>
+    <attributes/>
+    <GUI>
+      <xloc>2032</xloc>
+      <yloc>400</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>rows with marker</name>
+    <type>FilterRows</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <send_true_to>samples ok</send_true_to>
+    <send_false_to/>
+    <compare>
+      <condition>
+        <negated>N</negated>
+        <conditions>
+          <condition>
+            <negated>N</negated>
+            <leftvalue>setRowDataJson</leftvalue>
+            <function>CONTAINS</function>
+            <operator>AND</operator>
+            <value>
+              <name>constant</name>
+              <type>String</type>
+              <text>hop-graph-execution-info</text>
+              <length>-1</length>
+              <precision>-1</precision>
+              <isnull>N</isnull>
+              <mask/>
+            </value>
+          </condition>
+          <condition>
+            <negated>N</negated>
+            <leftvalue>collectionDate</leftvalue>
+            <function>IS NOT NULL</function>
+            <operator>-</operator>
+            <value>
+              <name>constant</name>
+              <type>String</type>
+              <text/>
+              <length>-1</length>
+              <precision>-1</precision>
+              <isnull>N</isnull>
+              <mask/>
+            </value>
+          </condition>
+        </conditions>
+      </condition>
+    </compare>
+    <attributes/>
+    <GUI>
+      <xloc>2208</xloc>
+      <yloc>400</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>samples ok</name>
+    <type>Dummy</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <attributes/>
+    <GUI>
+      <xloc>2384</xloc>
+      <yloc>400</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>no samples</name>
+    <type>DetectEmptyStream</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <attributes/>
+    <GUI>
+      <xloc>2384</xloc>
+      <yloc>528</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Abort no samples</name>
+    <type>Abort</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <abort_option>ABORT_WITH_ERROR</abort_option>
+    <always_log_rows>Y</always_log_rows>
+    <message>Execution samples did not contain the marker</message>
+    <row_threshold>0</row_threshold>
+    <attributes/>
+    <GUI>
+      <xloc>2560</xloc>
+      <yloc>528</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>find workflow</name>
+    <type>ExecInfo</type>
+    <description/>
+    <distribute>N</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <location>neo4j</location>
+    <operationType>FindLastExecution</operationType>
+    <idFieldName/>
+    <parentIdFieldName/>
+    <typeFieldName>workflowType</typeFieldName>
+    <nameFieldName>workflowName</nameFieldName>
+    <includeChildrenFieldName/>
+    <limitFieldName/>
+    <attributes/>
+    <GUI>
+      <xloc>1680</xloc>
+      <yloc>640</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>missing workflow</name>
+    <type>DetectEmptyStream</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <attributes/>
+    <GUI>
+      <xloc>1856</xloc>
+      <yloc>768</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Abort missing workflow</name>
+    <type>Abort</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <abort_option>ABORT_WITH_ERROR</abort_option>
+    <always_log_rows>Y</always_log_rows>
+    <message>The location did not return the subject workflow</message>
+    <row_threshold>0</row_threshold>
+    <attributes/>
+    <GUI>
+      <xloc>2032</xloc>
+      <yloc>768</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>check workflow</name>
+    <type>ScriptValueMod</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <optimizationLevel>9</optimizationLevel>
+    <jsScripts>
+      <jsScript>
+        <jsScript_type>0</jsScript_type>
+        <jsScript_name>Script 1</jsScript_name>
+        <jsScript_script><![CDATA[if (registrationDate == null) {
+  throw "Workflow execution is missing its registration date";
+}
+var DateFormat = Packages.java.text.SimpleDateFormat;
+var text = "" + new 
DateFormat("yyyy-MM-dd'T'HH:mm:ss").format(registrationDate);
+var expected = "" + loggedWorkflowDate;
+if (text != expected) {
+  throw "Workflow registrationDate was [" + text + "] expected [" + expected + 
"]";
+}
+]]></jsScript_script>
+      </jsScript>
+    </jsScripts>
+    <fields/>
+    <attributes/>
+    <GUI>
+      <xloc>1856</xloc>
+      <yloc>640</yloc>
+    </GUI>
+  </transform>
+  <transform_error_handling>
+  </transform_error_handling>
+  <attributes/>
+</pipeline>
diff --git 
a/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/subject-pipeline.hpl
 
b/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/subject-pipeline.hpl
new file mode 100644
index 0000000000..fc8c89a0d0
--- /dev/null
+++ 
b/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/subject-pipeline.hpl
@@ -0,0 +1,114 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<pipeline>
+  <info>
+    <name>subject-pipeline</name>
+    <name_sync_with_filename>Y</name_sync_with_filename>
+    <description>Three rows stored as execution samples by the Neo4j execution 
information location.</description>
+    <extended_description/>
+    <pipeline_version/>
+    <pipeline_type>Normal</pipeline_type>
+    <parameters>
+    </parameters>
+    <capture_transform_performance>N</capture_transform_performance>
+    
<transform_performance_capturing_delay>1000</transform_performance_capturing_delay>
+    
<transform_performance_capturing_size_limit>100</transform_performance_capturing_size_limit>
+    <created_user>-</created_user>
+    <created_date>2026/10/20 14:00:00.000</created_date>
+    <modified_user>-</modified_user>
+    <modified_date>2026/10/20 14:00:00.000</modified_date>
+  </info>
+  <notepads>
+  </notepads>
+  <order>
+    <hop>
+      <from>value</from>
+      <to>done</to>
+      <enabled>Y</enabled>
+    </hop>
+  </order>
+  <transform>
+    <name>value</name>
+    <type>DataGrid</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <data>
+      <line>
+        <item>hop-graph-execution-info</item>
+        <item>1</item>
+      </line>
+      <line>
+        <item>hop-graph-execution-info</item>
+        <item>2</item>
+      </line>
+      <line>
+        <item>hop-graph-execution-info</item>
+        <item>3</item>
+      </line>
+    </data>
+    <fields>
+      <field>
+        <length>-1</length>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+        <name>marker</name>
+        <type>String</type>
+      </field>
+      <field>
+        <length>-1</length>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+        <name>nr</name>
+        <type>Integer</type>
+      </field>
+    </fields>
+    <attributes/>
+    <GUI>
+      <xloc>128</xloc>
+      <yloc>96</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>done</name>
+    <type>Dummy</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <attributes/>
+    <GUI>
+      <xloc>320</xloc>
+      <yloc>96</yloc>
+    </GUI>
+  </transform>
+  <transform_error_handling>
+  </transform_error_handling>
+  <attributes/>
+</pipeline>
diff --git 
a/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/subject-workflow.hwf
 
b/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/subject-workflow.hwf
new file mode 100644
index 0000000000..d06f7ba05c
--- /dev/null
+++ 
b/integration-tests/neo4j/tests/neo4j-execution-info-roundtrip/subject-workflow.hwf
@@ -0,0 +1,93 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<workflow>
+  <name>subject-workflow</name>
+  <name_sync_with_filename>Y</name_sync_with_filename>
+  <description>Runs the subject pipeline with execution samples stored in 
Neo4j.</description>
+  <extended_description/>
+  <workflow_version/>
+  <created_user>-</created_user>
+  <created_date>2026/10/20 14:00:00.000</created_date>
+  <modified_user>-</modified_user>
+  <modified_date>2026/10/20 14:00:00.000</modified_date>
+  <parameters>
+  </parameters>
+  <actions>
+    <action>
+      <name>Start</name>
+      <description/>
+      <type>SPECIAL</type>
+      <attributes/>
+      <repeat>N</repeat>
+      <schedulerType>0</schedulerType>
+      <intervalSeconds>0</intervalSeconds>
+      <intervalMinutes>60</intervalMinutes>
+      <hour>12</hour>
+      <minutes>0</minutes>
+      <weekDay>1</weekDay>
+      <DayOfMonth>1</DayOfMonth>
+      <parallel>N</parallel>
+      <xloc>176</xloc>
+      <yloc>128</yloc>
+      <attributes_hac/>
+    </action>
+    <action>
+      <name>subject-pipeline.hpl</name>
+      <description/>
+      <type>PIPELINE</type>
+      <attributes/>
+      
<filename>${PROJECT_HOME}/tests/neo4j-execution-info-roundtrip/subject-pipeline.hpl</filename>
+      <params_from_previous>N</params_from_previous>
+      <exec_per_row>N</exec_per_row>
+      <clear_rows>N</clear_rows>
+      <clear_files>N</clear_files>
+      <set_logfile>N</set_logfile>
+      <logfile/>
+      <logext/>
+      <add_date>N</add_date>
+      <add_time>N</add_time>
+      <loglevel>Basic</loglevel>
+      <set_append_logfile>N</set_append_logfile>
+      <wait_until_finished>Y</wait_until_finished>
+      <follow_abort_remote>N</follow_abort_remote>
+      <create_parent_folder>N</create_parent_folder>
+      <run_configuration>local-graph-location</run_configuration>
+      <parameters>
+        <pass_all_parameters>Y</pass_all_parameters>
+      </parameters>
+      <parallel>N</parallel>
+      <xloc>400</xloc>
+      <yloc>128</yloc>
+      <attributes_hac/>
+    </action>
+  </actions>
+  <hops>
+    <hop>
+      <from>Start</from>
+      <to>subject-pipeline.hpl</to>
+      <enabled>Y</enabled>
+      <evaluation>Y</evaluation>
+      <unconditional>Y</unconditional>
+    </hop>
+  </hops>
+  <notepads>
+  </notepads>
+  <attributes/>
+</workflow>
diff --git 
a/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/execution/NeoExecutionInfoLocation.java
 
b/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/execution/NeoExecutionInfoLocation.java
index abf952a2d0..fbc713ebfd 100644
--- 
a/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/execution/NeoExecutionInfoLocation.java
+++ 
b/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/execution/NeoExecutionInfoLocation.java
@@ -27,7 +27,6 @@ import java.sql.Timestamp;
 import java.time.LocalDate;
 import java.time.LocalDateTime;
 import java.time.OffsetDateTime;
-import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.util.ArrayList;
 import java.util.Base64;
@@ -75,6 +74,7 @@ import org.apache.hop.execution.IExecutionInfoLocation;
 import org.apache.hop.execution.IExecutionMatcher;
 import org.apache.hop.execution.IExecutionSelector;
 import org.apache.hop.execution.LastPeriod;
+import org.apache.hop.execution.ListedExecution;
 import org.apache.hop.execution.plugin.ExecutionInfoLocationPlugin;
 import org.apache.hop.metadata.api.HopMetadataProperty;
 import org.apache.hop.metadata.api.IHopMetadataProvider;
@@ -90,6 +90,7 @@ import 
org.apache.hop.neo4j.execution.builder.CypherQueryBuilder;
 import org.apache.hop.neo4j.execution.builder.CypherRelationshipBuilder;
 import org.apache.hop.neo4j.execution.builder.ICypherBuilder;
 import org.apache.hop.neo4j.execution.cache.NeoLocationCache;
+import org.apache.hop.neo4j.logging.util.LoggingCore;
 import org.apache.hop.neo4j.shared.CypherConnectionSelectionLine;
 import org.apache.hop.neo4j.shared.NamedGraphConnection;
 import org.apache.hop.neo4j.shared.NeoConnectionUtils;
@@ -253,6 +254,9 @@ public class NeoExecutionInfoLocation implements 
IExecutionInfoLocation {
       throw new HopException("Error closing graph database execution 
information location", e);
     } finally {
       connection = null;
+      // The cache is static and shared by every location in this JVM. A 
finished engine must
+      // not keep serving its copy to the next reader.
+      NeoLocationCache.clear();
     }
   }
 
@@ -912,8 +916,6 @@ public class NeoExecutionInfoLocation implements 
IExecutionInfoLocation {
 
   public List<String> findNeo4jExecutionIDs(
       IGraphTransaction transaction, IExecutionSelector selector) {
-    List<String> ids = new ArrayList<>();
-
     CypherQueryBuilder builder =
         CypherQueryBuilder.of().withLabelAndKeys("n", EL_EXECUTION, Map.of());
 
@@ -992,18 +994,78 @@ public class NeoExecutionInfoLocation implements 
IExecutionInfoLocation {
     builder.withLimit(50);
 
     List<Map<String, Object>> result = run(transaction, builder.cypher(), 
builder.parameters());
-    for (Map<String, Object> record : result) {
+    return idsOfReadableExecutions(result, selector);
+  }
+
+  /**
+   * Ids of the executions in one list result that can be read. A node that 
cannot be read is
+   * skipped, so the other executions still show (issue #9039).
+   */
+  List<String> idsOfReadableExecutions(
+      List<Map<String, Object>> records, IExecutionSelector selector) {
+    List<String> ids = new ArrayList<>();
+    for (Map<String, Object> record : records) {
       String executionId = getString(record, EP_ID);
-      Execution execution = buildExecution(executionId, record);
-      ExecutionState state = buildExecutionState(executionId, record, "");
-      if (selector.isSelected(execution) && selector.isSelected(state)) {
-        ids.add(executionId);
+      try {
+        Execution execution = buildExecution(executionId, record);
+        ExecutionState state = buildExecutionState(executionId, record, "");
+        if (selector.isSelected(execution) && selector.isSelected(state)) {
+          ids.add(executionId);
+        }
+      } catch (Exception e) {
+        logReadError(executionId, e);
       }
     }
-
     return ids;
   }
 
+  /**
+   * One execution that cannot be read is skipped. A failure reading the 
location itself still fails
+   * the list (issue #9039).
+   */
+  @Override
+  public List<ListedExecution> listExecutions(IExecutionSelector selector) 
throws HopException {
+    IExecutionSelector active = selector == null ? IExecutionSelector.ALL : 
selector;
+    List<String> ids = findExecutionIDs(active);
+    List<ListedExecution> listed = new ArrayList<>();
+    Exception firstFailure = null;
+    int failures = 0;
+    for (String id : ids) {
+      try {
+        Execution execution = getExecution(id);
+        if (execution == null || !active.isSelected(execution)) {
+          continue;
+        }
+        ExecutionState state = getExecutionState(id);
+        if (!active.isSelected(state)) {
+          continue;
+        }
+        listed.add(new ListedExecution(execution, state));
+      } catch (Exception e) {
+        failures++;
+        if (firstFailure == null) {
+          firstFailure = e;
+        }
+        logReadError(id, e);
+      }
+    }
+    // Every id failed, for example because the connection dropped. Keep the 
location error.
+    //
+    if (listed.isEmpty() && failures > 0) {
+      if (firstFailure instanceof HopException hopException) {
+        throw hopException;
+      }
+      throw new HopException(CONST_ERROR_GETTING_EXECUTION_FROM_NEO_4_J, 
firstFailure);
+    }
+    return listed;
+  }
+
+  private void logReadError(String executionId, Exception e) {
+    if (log != null) {
+      log.logError("Error reading execution " + executionId + " from Neo4j 
(non-fatal)", e);
+    }
+  }
+
   @Override
   public void updateExecutionState(ExecutionState executionState) throws 
HopException {
     synchronized (this) {
@@ -1310,8 +1372,7 @@ public class NeoExecutionInfoLocation implements 
IExecutionInfoLocation {
           executions.add(execution);
         }
       } catch (Exception e) {
-        log.logError(
-            "Error loading execution with id : " + executionId + " from Neo4j 
(non-fatal)", e);
+        logReadError(executionId, e);
       }
     }
     return executions;
@@ -1335,9 +1396,13 @@ public class NeoExecutionInfoLocation implements 
IExecutionInfoLocation {
     // Get all
     List<String> ids = getNeo4jExecutionIds(transaction, true, 0);
     for (String id : ids) {
-      Execution execution = getNeo4jExecution(transaction, id);
-      if (execution != null && matcher.matches(execution)) {
-        executions.add(execution);
+      try {
+        Execution execution = getNeo4jExecution(transaction, id);
+        if (execution != null && matcher.matches(execution)) {
+          executions.add(execution);
+        }
+      } catch (Exception e) {
+        logReadError(id, e);
       }
     }
     return executions;
@@ -1831,7 +1896,7 @@ public class NeoExecutionInfoLocation implements 
IExecutionInfoLocation {
       case IValueMeta.TYPE_STRING -> value.toString();
       case IValueMeta.TYPE_INTEGER ->
           value instanceof Number number ? number.longValue() : 
Long.valueOf(value.toString());
-      case IValueMeta.TYPE_DATE -> toDate(value);
+      case IValueMeta.TYPE_DATE -> dateValue(value);
       case IValueMeta.TYPE_BOOLEAN ->
           value instanceof Boolean bool ? bool : 
Boolean.valueOf(value.toString());
       case IValueMeta.TYPE_NUMBER ->
@@ -2043,12 +2108,19 @@ public class NeoExecutionInfoLocation implements 
IExecutionInfoLocation {
   }
 
   private Date getDate(Map<String, Object> record, String key) {
-    return toDate(record.get("n." + key));
+    Object value = record.get("n." + key);
+    Date date = toDate(value);
+    if (date == null && value != null && !value.toString().isBlank() && log != 
null) {
+      log.logError("Unable to parse execution " + key + " '" + value + "' 
(left empty)");
+    }
+    return date;
   }
 
   /**
-   * A date and time as the graph databases return them: a LocalDateTime from 
Neo4j and Memgraph, an
-   * ISO string from FalkorDB and Apache AGE.
+   * A date and time as the graph databases return them: a {@link 
LocalDateTime} from Neo4j and
+   * Memgraph, an ISO-8601 string from FalkorDB and Apache AGE, or the {@code 
yyyy/MM/dd'T'HH:mm:ss}
+   * string Neo4j logging stores. A value that is not a date is null, so one 
bad property does not
+   * fail the read of every execution (issue #9039).
    */
   public static Date toDate(Object value) {
     if (value == null) {
@@ -2058,7 +2130,7 @@ public class NeoExecutionInfoLocation implements 
IExecutionInfoLocation {
       return date;
     }
     if (value instanceof LocalDateTime localDateTime) {
-      return 
Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
+      return LoggingCore.toDate(localDateTime);
     }
     if (value instanceof ZonedDateTime zonedDateTime) {
       return Date.from(zonedDateTime.toInstant());
@@ -2067,13 +2139,21 @@ public class NeoExecutionInfoLocation implements 
IExecutionInfoLocation {
       return Date.from(offsetDateTime.toInstant());
     }
     if (value instanceof LocalDate localDate) {
-      return 
Date.from(localDate.atStartOfDay(ZoneId.systemDefault()).toInstant());
+      return LoggingCore.toDate(localDate.atStartOfDay());
     }
-    String string = value.toString();
-    if (string.isEmpty()) {
-      return null;
+    return LoggingCore.parseDate(value.toString());
+  }
+
+  /**
+   * A sampled date. An unparsable value is reported on that cell, unlike 
{@link #toDate}, which
+   * leaves an execution date empty so the execution can still be listed.
+   */
+  private static Date dateValue(Object value) {
+    Date date = toDate(value);
+    if (date == null && value != null && !value.toString().isBlank()) {
+      throw new HopRuntimeException("Unable to parse date value '" + value + 
"'");
     }
-    return 
Date.from(LocalDateTime.parse(string).atZone(ZoneId.systemDefault()).toInstant());
+    return date;
   }
 
   private String getString(Map<String, Object> record, String key) {
diff --git 
a/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/logging/util/LoggingCore.java
 
b/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/logging/util/LoggingCore.java
index 08381ae686..53ff8c5731 100644
--- 
a/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/logging/util/LoggingCore.java
+++ 
b/plugins/tech/neo4j/src/main/java/org/apache/hop/neo4j/logging/util/LoggingCore.java
@@ -24,7 +24,9 @@ import java.time.OffsetDateTime;
 import java.time.ZoneId;
 import java.time.ZonedDateTime;
 import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeFormatterBuilder;
 import java.time.format.DateTimeParseException;
+import java.time.temporal.ChronoField;
 import java.util.ArrayList;
 import java.util.Date;
 import java.util.HashMap;
@@ -55,6 +57,27 @@ public class LoggingCore {
   /** The format Neo4j logging stores the registration date of an execution 
in. */
   public static final String REGISTRATION_DATE_FORMAT = 
"yyyy/MM/dd'T'HH:mm:ss";
 
+  /** Logging dates, with an optional fraction of a second. */
+  private static final DateTimeFormatter REGISTRATION_DATE_TIME =
+      new DateTimeFormatterBuilder()
+          .appendPattern(REGISTRATION_DATE_FORMAT)
+          .optionalStart()
+          .appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, true)
+          .optionalEnd()
+          .toFormatter();
+
+  /** Timestamp strings written for a graph property, with an optional 
fraction of a second. */
+  private static final DateTimeFormatter LOCAL_DATE_TIME_SPACE =
+      new DateTimeFormatterBuilder()
+          .appendPattern("yyyy-MM-dd HH:mm:ss")
+          .optionalStart()
+          .appendFraction(ChronoField.NANO_OF_SECOND, 1, 9, true)
+          .optionalEnd()
+          .toFormatter();
+
+  private static final List<DateTimeFormatter> LOCAL_DATE_TIMES =
+      List.of(REGISTRATION_DATE_TIME, DateTimeFormatter.ISO_LOCAL_DATE_TIME, 
LOCAL_DATE_TIME_SPACE);
+
   /**
    * The name of the connection to log to: {@link 
Defaults#HOP_GRAPH_LOGGING_CONNECTION} or else
    * {@link Defaults#NEO4J_LOGGING_CONNECTION}. Null if logging is disabled.
@@ -284,21 +307,45 @@ public class LoggingCore {
     return null;
   }
 
-  private static Date parseDate(String string) {
-    for (DateTimeFormatter formatter :
-        List.of(
-            DateTimeFormatter.ofPattern(REGISTRATION_DATE_FORMAT),
-            DateTimeFormatter.ISO_LOCAL_DATE_TIME)) {
+  /**
+   * A date stored as text on an execution. Neo4j logging writes {@link 
#REGISTRATION_DATE_FORMAT}.
+   * FalkorDB and Apache AGE write an ISO-8601 local date time, and a 
timestamp property can be a
+   * local date time separated with a space. An offset or a zoned value is 
read as that instant.
+   * Anything else is null, so one bad value does not fail the read (issue 
#9039).
+   */
+  public static Date parseDate(String string) {
+    if (string == null) {
+      return null;
+    }
+    String trimmed = string.trim();
+    if (trimmed.isEmpty()) {
+      return null;
+    }
+    for (DateTimeFormatter formatter : LOCAL_DATE_TIMES) {
       try {
-        return toDate(LocalDateTime.parse(string, formatter));
+        return toDate(LocalDateTime.parse(trimmed, formatter));
       } catch (DateTimeParseException e) {
         // Try the next format
       }
     }
-    return null;
+    try {
+      return Date.from(OffsetDateTime.parse(trimmed).toInstant());
+    } catch (DateTimeParseException e) {
+      // Try the next format
+    }
+    try {
+      return Date.from(ZonedDateTime.parse(trimmed).toInstant());
+    } catch (DateTimeParseException e) {
+      // Try the next format
+    }
+    try {
+      return toDate(LocalDate.parse(trimmed).atStartOfDay());
+    } catch (DateTimeParseException e) {
+      return null;
+    }
   }
 
-  private static Date toDate(LocalDateTime localDateTime) {
+  public static Date toDate(LocalDateTime localDateTime) {
     return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
   }
 
diff --git 
a/plugins/tech/neo4j/src/test/java/org/apache/hop/neo4j/execution/NeoExecutionInfoLocationReadTest.java
 
b/plugins/tech/neo4j/src/test/java/org/apache/hop/neo4j/execution/NeoExecutionInfoLocationReadTest.java
new file mode 100644
index 0000000000..dda775eb6b
--- /dev/null
+++ 
b/plugins/tech/neo4j/src/test/java/org/apache/hop/neo4j/execution/NeoExecutionInfoLocationReadTest.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *       http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.hop.neo4j.execution;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNull;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
+import java.time.ZoneId;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import org.apache.hop.core.exception.HopRuntimeException;
+import org.apache.hop.core.row.value.ValueMetaDate;
+import org.apache.hop.execution.IExecutionSelector;
+import org.junit.jupiter.api.Test;
+
+/** Reading execution dates must survive the text Neo4j logging stores, see 
issue #9039. */
+class NeoExecutionInfoLocationReadTest {
+
+  private static Date at(int year, int month, int day, int hour, int minute, 
int second) {
+    return Date.from(
+        LocalDateTime.of(year, month, day, hour, minute, second)
+            .atZone(ZoneId.systemDefault())
+            .toInstant());
+  }
+
+  @Test
+  void loggingRegistrationDateIsRead() {
+    Date registered = at(2026, 10, 7, 16, 8, 52);
+
+    assertEquals(registered, 
NeoExecutionInfoLocation.toDate("2026/10/07T16:08:52"));
+    assertEquals(registered, 
NeoExecutionInfoLocation.toDate("2026-10-07T16:08:52"));
+    assertEquals(registered, NeoExecutionInfoLocation.toDate("2026-10-07 
16:08:52"));
+    assertEquals(
+        registered, NeoExecutionInfoLocation.toDate(LocalDateTime.of(2026, 10, 
7, 16, 8, 52)));
+    assertEquals(
+        Date.from(OffsetDateTime.parse("2026-10-07T14:08:52Z").toInstant()),
+        NeoExecutionInfoLocation.toDate("2026-10-07T14:08:52Z"));
+  }
+
+  @Test
+  void unparsableDateIsEmpty() {
+    assertNull(NeoExecutionInfoLocation.toDate(null));
+    assertNull(NeoExecutionInfoLocation.toDate(""));
+    assertNull(NeoExecutionInfoLocation.toDate("   "));
+    assertNull(NeoExecutionInfoLocation.toDate("not a date"));
+    assertNull(NeoExecutionInfoLocation.toDate(42));
+  }
+
+  @Test
+  void sampledDateReportsABadValueOnThatCell() {
+    ValueMetaDate when = new ValueMetaDate("when");
+
+    assertEquals(
+        at(2026, 10, 7, 16, 8, 52),
+        NeoExecutionInfoLocation.extractHopValue(when, "2026/10/07T16:08:52"));
+    assertNull(NeoExecutionInfoLocation.extractHopValue(when, ""));
+    assertThrows(
+        HopRuntimeException.class,
+        () -> NeoExecutionInfoLocation.extractHopValue(when, "not a date"));
+  }
+
+  @Test
+  void oneUnreadableExecutionDoesNotHideTheOthers() {
+    Map<String, Object> badDetails = execution("bad-details", "Workflow", 
null);
+    badDetails.put("n.details", "{");
+
+    List<String> ids =
+        new NeoExecutionInfoLocation()
+            .idsOfReadableExecutions(
+                List.of(
+                    execution("good", "Pipeline", LocalDateTime.of(2026, 10, 
7, 16, 8, 52)),
+                    execution("bad-type", "PIPELINE", "2026/10/07T16:08:52"),
+                    execution("logging", "Pipeline", "2026/10/07T16:08:52"),
+                    badDetails,
+                    execution("later", "Workflow", "not a date")),
+                IExecutionSelector.ALL);
+
+    assertEquals(List.of("good", "logging", "later"), ids);
+  }
+
+  /** A row as {@link NeoExecutionInfoLocation} reads it back from a Cypher 
result. */
+  private static Map<String, Object> execution(String id, String type, Object 
registrationDate) {
+    Map<String, Object> record = new HashMap<>();
+    record.put("n.id", id);
+    record.put("n.executionType", type);
+    record.put("n.name", id);
+    if (registrationDate != null) {
+      record.put("n.registrationDate", registrationDate);
+    }
+    return record;
+  }
+}
diff --git 
a/plugins/tech/neo4j/src/test/java/org/apache/hop/neo4j/logging/util/LoggingCoreTest.java
 
b/plugins/tech/neo4j/src/test/java/org/apache/hop/neo4j/logging/util/LoggingCoreTest.java
index 0138b16ee2..c46267f62e 100644
--- 
a/plugins/tech/neo4j/src/test/java/org/apache/hop/neo4j/logging/util/LoggingCoreTest.java
+++ 
b/plugins/tech/neo4j/src/test/java/org/apache/hop/neo4j/logging/util/LoggingCoreTest.java
@@ -21,6 +21,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNull;
 
 import java.time.LocalDateTime;
+import java.time.OffsetDateTime;
 import java.time.ZoneId;
 import java.time.ZoneOffset;
 import java.time.ZonedDateTime;
@@ -80,7 +81,28 @@ class LoggingCoreTest {
   }
 
   @Test
-  void unparsableStringIsNull() {
+  void loggingDateReportedByTheExecutionInformationLocation() {
+    // Issue #9039: Neo4j logging stores this text, and the execution list has 
to read it.
+    assertEquals(
+        toDate(LocalDateTime.of(2026, 10, 7, 16, 8, 52)),
+        LoggingCore.parseDate("2026/10/07T16:08:52"));
+  }
+
+  @Test
+  void timestampTextAndOffset() {
+    assertEquals(
+        toDate(LocalDateTime.of(2026, 9, 30, 14, 15, 16)),
+        LoggingCore.parseDate("2026-09-30 14:15:16.000000000"));
+    assertEquals(
+        Date.from(OffsetDateTime.parse("2026-09-30T12:15:16Z").toInstant()),
+        LoggingCore.parseDate("2026-09-30T12:15:16Z"));
+  }
+
+  @Test
+  void blankOrUnparsableStringIsNull() {
+    assertNull(LoggingCore.parseDate(null));
+    assertNull(LoggingCore.parseDate(""));
+    assertNull(LoggingCore.parseDate("   "));
     assertNull(LoggingCore.getDateValue(execution("not a date"), 
"registrationDate"));
   }
 

Reply via email to