Runtime error with preSavePageFunction

I created a preSavePageFunction to use with Dynamics CRM/365 exports. When data is exported using OData, and formatted values are requested, the tags that come back cause issues with handlebar expressions. I created the function to shorten the tags, and pull out the part causing the issue (@OData.Community.Display.V1.Formatted). The function works great in preview, but when I run the flow I get the error “TypeError: Cannot set property 'etag' of undefined”. Can anyone help me with the difference between runtime and preview?

Here’s some sample data:

{
    "@odata.etag": "W/\"1045255693\"",
    "modifiedon@OData.Community.Display.V1.FormattedValue": "10/7/2025 5:27 PM",
    "modifiedon": "2025-10-07T21:27:55Z",
    "_owninguser_value": "f4c6312c-9c31-e611-80e2-5065f38af911",
    "_hisol_transfertoproduct_value": null,
    "hisol_transferproductsku": "",
    "_transactioncurrencyid_value": null,
    "_hisol_approver_value@OData.Community.Display.V1.FormattedValue": "Integration Admin",
}

Can you log the payload during runtime?

console.log(JSON.stringify(payload));

Hi, Jim.

The sample data is invalid JSON, specifically at the @odata.etag key. Since the script references this key at line 60, it cannot read its value and returns the following error:
**“TypeError: Cannot set property 'etag' of undefined.”

Invalid quoting in the @odata.etag value**

"@odata.etag": "W/"1045255693""

What’s wrong

Inside the string, there are unescaped double quotes ("1045255693").
JSON only allows double quotes around entire strings, not unescaped inside them.
So when the parser reaches the second ", it thinks the string ended early—causing a syntax error.

I tested the script in my test account using a valid JSON, and the flow was able to process the data

1 Like

Thanks for the help! When I copied and pasted the data, the escape characters for the quotes were lost somehow. The error/retry data that showed with the error did look like this:

"@odata.etag": "W\/"1045255693\"",

I changed the script to skip the odata.etag key/value pair completely, and then I get the error:

TypeError: Cannot set property 'modifiedon_FValue' of undefined

so it’s not a problem with the data on that specific key/value pair. It’s a problem with the code that only shows when running the flow, but not in preview.

Here’s the results of the console.log:

{
    "data": [
        {
            "@odata.etag": "W/\"1003583353\"",
            "modifiedon@OData.Community.Display.V1.FormattedValue": "9/26/2024 4:18 PM",
            "modifiedon": "2024-09-26T20:18:07Z",
            "_owninguser_value": "f4c6312c-9c31-e611-80e2-5065f38af911",
            "_hisol_transfertoproduct_value": null,
            "hisol_transferproductsku": "",
            "_transactioncurrencyid_value": null,
            "_hisol_approver_value@OData.Community.Display.V1.FormattedValue": "Shogo Nakanishi",
            "_hisol_approver_value": "6e05b16e-dbd9-eb11-bacb-000d3a4faa1a",
            "overriddencreatedon": null,
            "hisol_productinventoryadjustmentid": "50db59ed-417c-ef11-a671-000d3a9b8ce2",
            "hisol_action@OData.Community.Display.V1.FormattedValue": "Issue In",
            "hisol_action": 337290001,
            "importsequencenumber": null,
            "hisol_finalapprovalapproveddate": null,
            "hisol_productsku": "MNS75700ARXWL160",
            "_modifiedonbehalfby_value": null,
            "exchangerate": null,
            "hisol_note": null,
            "statecode@OData.Community.Display.V1.FormattedValue": "Active",
            "statecode": 0,
            "hisol_distributionaccount": null,
            "hisol_senttogpdatetime": null,
            "_hisol_finalapproval_value": null,
            "hisol_unitcost_base": null,
            "hisol_rejectednotes": null,
            "versionnumber@OData.Community.Display.V1.FormattedValue": "1,003,583,353",
            "versionnumber": 1003583353,
            "hisol_gpadjustment": null,
            "hisol_reason@OData.Community.Display.V1.FormattedValue": "Inventory Adjustment",
            "hisol_reason": 337290002,
            "utcconversiontimezonecode": null,
            "_hisol_vendormemo_value": null,
            "hisol_adjustcostintargetproduct@OData.Community.Display.V1.FormattedValue": "No",
            "hisol_adjustcostintargetproduct": false,
            "hisol_consignmentproduct@OData.Community.Display.V1.FormattedValue": "No",
            "hisol_consignmentproduct": false,
            "hisol_quantity@OData.Community.Display.V1.FormattedValue": "1",
            "hisol_quantity": 1,
            "_createdonbehalfby_value": null,
            "_modifiedby_value@OData.Community.Display.V1.FormattedValue": "Integration Admin",
            "_modifiedby_value": "f4c6312c-9c31-e611-80e2-5065f38af911",
            "_hisol_product_value@OData.Community.Display.V1.FormattedValue": "Basic Akoya Pearl Necklace",
            "_hisol_product_value": "d770a50c-8bec-ea11-a817-000d3a4e2024",
            "createdon@OData.Community.Display.V1.FormattedValue": "9/26/2024 4:00 PM",
            "createdon": "2024-09-26T20:00:09Z",
            "hisol_unitcost": null,
            "_owningbusinessunit_value@OData.Community.Display.V1.FormattedValue": "mikimotoamericadev",
            "_owningbusinessunit_value": "5d01ba88-7c22-e611-80e5-5065f38a49a1",
            "hisol_rejected@OData.Community.Display.V1.FormattedValue": "No",
            "hisol_rejected": false,
            "statuscode@OData.Community.Display.V1.FormattedValue": "Approved",
            "statuscode": 337290001,
            "_createdby_value@OData.Community.Display.V1.FormattedValue": "Integration Admin",
            "_createdby_value": "f4c6312c-9c31-e611-80e2-5065f38af911",
            "_ownerid_value@OData.Community.Display.V1.FormattedValue": "Integration Admin",
            "_ownerid_value": "f4c6312c-9c31-e611-80e2-5065f38af911",
            "_owningteam_value": null,
            "timezoneruleversionnumber": null,
            "hisol_name": "Issue In on 09-26-2024 by Integration Admin",
            "owninguser": {
                "ownerid": "f4c6312c-9c31-e611-80e2-5065f38af911",
                "firstname": "Integration",
                "lastname": "Admin",
                "systemuserid": "f4c6312c-9c31-e611-80e2-5065f38af911"
            },
            "action": 1,
            "xBatch": "XReceive-",
            "nonXBatch": "REC-ADJ-",
            "xUser": "IAdmi",
            "io_custom_trace_key": "50db59ed-417c-ef11-a671-000d3a9b8ce2"
        },
        {
            "@odata.etag": "W/\"1045255693\"",
            "modifiedon@OData.Community.Display.V1.FormattedValue": "10/7/2025 5:27 PM",
            "modifiedon": "2025-10-07T21:27:55Z",
            "_owninguser_value": "f4c6312c-9c31-e611-80e2-5065f38af911",
            "_hisol_transfertoproduct_value": null,
            "hisol_transferproductsku": "",
            "_transactioncurrencyid_value": null,
            "_hisol_approver_value@OData.Community.Display.V1.FormattedValue": "Integration Admin",
            "_hisol_approver_value": "f4c6312c-9c31-e611-80e2-5065f38af911",
            "overriddencreatedon": null,
            "hisol_productinventoryadjustmentid": "522d5126-c4a3-f011-bbd2-7c1e52593f2f",
            "hisol_action@OData.Community.Display.V1.FormattedValue": "Return Memo Items",
            "hisol_action": 337290003,
            "importsequencenumber": null,
            "hisol_finalapprovalapproveddate@OData.Community.Display.V1.FormattedValue": "10/7/2025",
            "hisol_finalapprovalapproveddate": "2025-10-07T04:00:00Z",
            "hisol_productsku": "",
            "_modifiedonbehalfby_value": null,
            "exchangerate": null,
            "hisol_note": null,
            "statecode@OData.Community.Display.V1.FormattedValue": "Active",
            "statecode": 0,
            "hisol_distributionaccount@OData.Community.Display.V1.FormattedValue": "Consignment Return (15100-0000)",
            "hisol_distributionaccount": 337290001,
            "hisol_senttogpdatetime": null,
            "_hisol_finalapproval_value@OData.Community.Display.V1.FormattedValue": "Integration Admin",
            "_hisol_finalapproval_value": "f4c6312c-9c31-e611-80e2-5065f38af911",
            "hisol_unitcost_base": null,
            "hisol_rejectednotes": null,
            "versionnumber@OData.Community.Display.V1.FormattedValue": "1,045,255,693",
            "versionnumber": 1045255693,
            "hisol_gpadjustment": null,
            "hisol_reason": null,
            "utcconversiontimezonecode": null,
            "_hisol_vendormemo_value@OData.Community.Display.V1.FormattedValue": "102000000332",
            "_hisol_vendormemo_value": "552bb196-535a-ef11-a316-00224823f94c",
            "hisol_adjustcostintargetproduct@OData.Community.Display.V1.FormattedValue": "No",
            "hisol_adjustcostintargetproduct": false,
            "hisol_consignmentproduct": null,
            "hisol_quantity": null,
            "_createdonbehalfby_value": null,
            "_modifiedby_value@OData.Community.Display.V1.FormattedValue": "Integration Admin",
            "_modifiedby_value": "f4c6312c-9c31-e611-80e2-5065f38af911",
            "_hisol_product_value": null,
            "createdon@OData.Community.Display.V1.FormattedValue": "10/7/2025 5:25 PM",
            "createdon": "2025-10-07T21:25:34Z",
            "hisol_unitcost": null,
            "_owningbusinessunit_value@OData.Community.Display.V1.FormattedValue": "mikimotoamericadev",
            "_owningbusinessunit_value": "5d01ba88-7c22-e611-80e5-5065f38a49a1",
            "hisol_rejected@OData.Community.Display.V1.FormattedValue": "No",
            "hisol_rejected": false,
            "statuscode@OData.Community.Display.V1.FormattedValue": "Approved",
            "statuscode": 337290001,
            "_createdby_value@OData.Community.Display.V1.FormattedValue": "Integration Admin",
            "_createdby_value": "f4c6312c-9c31-e611-80e2-5065f38af911",
            "_ownerid_value@OData.Community.Display.V1.FormattedValue": "Integration Admin",
            "_ownerid_value": "f4c6312c-9c31-e611-80e2-5065f38af911",
            "_owningteam_value": null,
            "timezoneruleversionnumber@OData.Community.Display.V1.FormattedValue": "0",
            "timezoneruleversionnumber": 0,
            "hisol_name": "Return Memo Items on 10/7/2025 by Integration Admin",
            "owninguser": {
                "ownerid": "f4c6312c-9c31-e611-80e2-5065f38af911",
                "firstname": "Integration",
                "lastname": "Admin",
                "systemuserid": "f4c6312c-9c31-e611-80e2-5065f38af911"
            },
            "action": 0,
            "xBatch": "XUsed-",
            "nonXBatch": "ISS-ADJ-",
            "xUser": "IAdmi",
            "io_custom_trace_key": "522d5126-c4a3-f011-bbd2-7c1e52593f2f"
        }\
    ],
    "errors": [],
    "files": [],
    "settings": {
        "export": {},
        "connection": {
            "microsoftDynamics365Subdomain": "mikimotoamericadev.crm"
        },
        "integration": {
            "EComEmailRecips": "LCipperly@mikimotoamerica.com; CVelasquez@mikimotoamerica.com",
            "EComEmailCCRecips": "SNakanishi@mikimotoamerica.com; NOtsuka@mikimotoamerica.com"
        }
    },
    "configuration": {},
    "_exportId": "68e581c4feb7b9819a74148b",
    "_connectionId": "68a32bfdaf2da8159ed4a7b2",
    "_flowId": "68e43756a2a9e1c70cf01434",
    "_integrationId": "68ac726ecaf7b011753c5aea",
    "pageContext": {
        "type": "microsoftdynamics365",
        "agent": false,
        "_id": "68a32bfdaf2da8159ed4a7b2",
        "_integrationId": "68ac726ecaf7b011753c5aea",
        "_flowId": "68e43756a2a9e1c70cf01434"
    },
    "pageIndex": 0,
    "sandbox": true,
    "testMode": false,
    "job": {
        "_id": "68e7f37a051d80e7f0ef00e9",
        "startedAt": "2025-10-09T17:40:10.956Z",
        "type": "export",
        "parentJob": {
            "_id": "68e7f37932f4017b731624ba",
            "type": "flow",
            "flowExecutionGroupId": "10695b3d383a46849a4c449e11ccd28e"
        }
    }
}

@Jim_Clarke we have a standard structure for preSavePage function. Can you please update the function input and return the data as per the structure provided in this article https://docs.celigo.com/hc/en-us/articles/20228312523931-JavaScript-hooks#javascript-hooks-0. Thanks.

1 Like

Please try the code below and let me know if it works.

function preSavePage (options) {
  const modifiedData = options.data.map(record => {
    if (typeof record === 'object' && record !== null) {
      const updatedRecord = {};
      for (const key in record) {
        const newKey = key.replace('@odata.', '').replace('@OData.Community.Display.V1.Formatted', '_F');
        updatedRecord[newKey] = record[key];
      }
      return updatedRecord;
    }
    return record;
  });

  return {
    data: modifiedData,
    errors: options.errors,
    abort: false,
    newErrorsAndRetryData: []
  };
}

1 Like

It is returning it in that structure.

Aila,

Whatever the issue was, that seems to have worked around it.

Thanks!

2 Likes

@Jim_Clarke - Input to preSavePage must always be an options object - you can’t change that signature. What Aila did was rewrite your original script logic so it accepts that options shape and uses Celigo’s integrator.io notation, while retaining your key-replacement logic.