Cannot save calculation rule after making any change to the expression

228
4
Jump to solution
3 weeks ago
ColeSutton
New Contributor II

I can add a new calculation rule, validate the expression, and save the rule... this works fine as expected.

But once that rule has been saved, I cannot alter the expression whatsoever. If I make any change to expression code, and then try to save those changes, I get the following:

ERROR 999999: Something unexpected caused the tool to fail. Contact Esri Technical Support (http://esriurl.com/support) to Report a Bug, and refer to the error help for potential solutions or workarounds.

This happens even when the change to the code is perfectly valid (syntax etc) or functionally meaningless (like if I change the text in a comment). Really the only way I can implement the change to the expression code is by deleting or disabling the existing rule, and adding/saving a brand new rule with the modified code.

Anyone else experiencing this? I haven't found any existing discussions about the issue. I already tried reinstalling Pro to see if it was a glitch unique to my install. The issue persists after reinstalling.

0 Kudos
1 Solution

Accepted Solutions
HusseinNasser2
Esri Contributor

Yeah there is a bug here, we are suppose to yell at you that you can't pass variables to FeatureSetByName, because we need the name to be static so we can resolve the table name to a registered geodatabase catalog id. 

 

Change your script wherever you have a featuresetbyname and pass in a literal string instead.

for example   

FeatureSetByName($datastore, addresspoint_fc, ['*'], true), firstPoint);

 

 

to , this and it should solve the problem

 

FeatureSetByName($datastore, "AddressPoint", ['*'], true), firstPoint);

 

 

Meanwhile we will fix the bug where it tells you the exact the error message instead of 9999 error. it shouldn't even let you save it to begin with. 

 

View solution in original post

4 Replies
HusseinNasser2
Esri Contributor

Hey Cole,

 

Can you share your pro version and the rule script you are working with? does this problem occur in the attribute rules view as well?

 

Does it work with simple rules? like create a new rule with return 0; can you then update it to add a comment? 

want to see if this is data specific or something else. 

 

 

0 Kudos
ColeSutton
New Contributor II

Hi Hussein,

I'm on Pro 3.2.2 right now. I experience the problem in the Attribute Rules view, as that's the only place I know of to view or edit the rules. Is there some other view or menu in Pro where this can be accomplished?


I tried a simple rule like you suggested. With the simple rule, I can save, then add a comment, then save again as expected. No problem there. Unfortunately, complex rules are the ones that require the most debugging, tweaking, and resaving. I can't help but wonder at what point exactly does a rule go from "simple enough" to "too complex". Or maybe it's not a matter of complexity but just some specific aspect of the code?

Here's the expression for the more complex rule I'm working with. Aside from not being able to save expression changes after initially saving, the rule does perform exactly as I want...

// This rule works by by drawing a driveway line from the Road Centerline to the Site Address Point.

// The first vertex must touch a Road Centerline.
// The last vertex must touch a Site Address Point.

// Checks for an existing Address Point sitting on Road Centerline at the first vertex.
// If no Address Point is present, one will be created.

// Address Points, Site Address Points and Driveway lines have their own unique IDs: ADD-#, SID-#, and DRW-#
// This rule will pull the SID-#, the new DRW-#, and the ADD-# (whether existing or newly created)
// The rule will push the DRW-# and ADD-# values into the Site Address Point foreign key fields.
// The rule will bring the SID-# and ADD-# into the Driveway line foreign key fields.


// Define the Driveway Line fields
Expects($feature, 'DRWID')
var drw_idfield = 'DRWID';
var drw_sapkeyfield = 'SITEADDID'; //note: string must be hard coded in return statement, variable name won't work (unless I set up a dictionary first using the variable names, then call the dictionary in the return statement (?) like "adds" array
var drw_adpkeyfield = 'ADDPTKEY';

//Define the Site Address Point feature class name
var siteaddress_fc = 'SiteAddressPoint';

// Define the Site Addresses fields
var sap_idfield = 'SITEADDID';
var sap_adpkeyfield = 'ADDPTKEY';
var sap_drwkeyfield = 'ENTID';

//Define the Address Point feature class name
var addresspoint_fc = 'AddressPoint';

// Define the Address Point fields
var adp_idfield = 'ADDRESSPTI';

//Define the Road Centerline feature class name
var roads_fc = 'RoadCenterline';

// This function will Get a new id for the address point
function getAddressPointID() {
    // Define the name of the database sequence and the format for the id
    var myId = NextSequenceValue("AddressPointID");
    return `ADD-${myId}`;
}

// Get the geometry and id (DRW-#) of the driveway line
var geom = Geometry($feature);
var myDrwID = $feature[drw_idfield];

// Get the vertices of the feature
var vertices = []
var firstPoint = null;
var lastPoint = null;
for (var part in geom.paths) {
    var segment = geom.paths[part];

    // Loop through the points in the segment
    for (var i in segment) {
        if (IsEmpty(firstPoint)) {
            firstPoint = segment[i];
            continue;
        }
        Push(vertices, segment[i]);
        lastPoint = segment[i];
    }
}

if (Count(vertices) < 1) return { "errorMessage" : "Line must have at least 2 vertices" }

// Find any intersecting roads with the first vertex
// If no roads intersect, return an error message, preventing the driveway and address point from being created
var intersectingRoads = Intersects(FeatureSetByName($datastore, roads_fc, ['*'], true), firstPoint);
if (Count(intersectingRoads) == 0) return { "errorMessage": "First vertex must intersect at least one Road Centerline" }

// Check for a Site Address Point intersecting with the last vertex
var intersectingSAP = Intersects(FeatureSetByName($datastore, siteaddress_fc, ['*'], true), lastPoint);
var mySAP = First(intersectingSAP);
var mysapGlobalID = "";
var mysapID = "";
if (mySAP == null){
    return { "errorMessage": "End point of Entrance Connection line must intersect one Site Address Point. None found." };
} else if (Count(intersectingSAP) != 1) {
    return { "errorMessage": "End point of Entrance Connection line must intersect one Site Address Point. More than one found." };
} else {
    mysapGlobalID = mySAP.globalID;
    mysapID = mySAP[sap_idfield];
}

// Check for an existing Address Point intersecting with the first vertex
// If none exists, create one.
// If one does exist, do not add a new one. Multiple driveways may originate at the same Address Point, even on opposite sides of the road. In such a case, the one Address Point is shared.
// More than one Address Point in the exact same spot is not expected.
var intersectingADP = Intersects(FeatureSetByName($datastore, addresspoint_fc, ['*'], true), firstPoint);
var adpCount = Count(intersectingADP);
var addressPointAdds = []
var addressptid = ""


if (adpCount == 0) {//There is no existing Address Point found
    // Get an ID for the new Address Point
    addressptid = getAddressPointID();
    // And Construct a Point object
    var myAdpPoint = Point({"x": firstPoint["x"], "y": firstPoint["y"], "spatialReference": Geometry($feature)["spatialReference"]})
    Push(addressPointAdds, {
        'attributes': Dictionary(
                        adp_idfield, addressptid
                    ), 
        'geometry': myAdpPoint
    })
} else if (adpCount > 1) {
    return { "errorMessage": "More than one Address Point in the exact same spot is not expected"}
} else if (adpCount == 1) {
    // Then get the ID of the existing Address Point
    var myIntAdp = First(intersectingADP)
    IIf(myIntAdp==null,null,addressptid = myIntAdp[adp_idfield])
}


return {
    'result': {//put SID-# and ADD-# into this driveway line
        'attributes': {
            "SITEADDID": mysapID,
            "ADDPTKEY": addressptid
        }
    },
    'edit': [{//put ADD-# and DRW-# into the Site Address Point
        'className': siteaddress_fc,
        'updates': [{
            'globalID': mysapGlobalID,
            'attributes': {
                'ADDPTKEY': addressptid,
                'ENTID': myDrwID
            }
        }]
    }, {//add new AddressPoint (if an existing one was not detected)
        'className': addresspoint_fc,
        'adds': addressPointAdds
    }]
}

 

And for what it's worth, here are the rule options I'm using: just the "Insert" trigger and "Exclude from application evaluation"

ColeSutton_2-1714660026504.png

 

0 Kudos
HusseinNasser2
Esri Contributor

Yeah there is a bug here, we are suppose to yell at you that you can't pass variables to FeatureSetByName, because we need the name to be static so we can resolve the table name to a registered geodatabase catalog id. 

 

Change your script wherever you have a featuresetbyname and pass in a literal string instead.

for example   

FeatureSetByName($datastore, addresspoint_fc, ['*'], true), firstPoint);

 

 

to , this and it should solve the problem

 

FeatureSetByName($datastore, "AddressPoint", ['*'], true), firstPoint);

 

 

Meanwhile we will fix the bug where it tells you the exact the error message instead of 9999 error. it shouldn't even let you save it to begin with. 

 

ColeSutton
New Contributor II

Ah, I see now in the FeatureSetByName parameter definitions: the title "...must be a text literal." Never caught that bit until now. Glad to hear the error message fix is on the way. Thanks for your help!

I recently stumbled into a similar limitation, which I'm not sure is articulated in the documentation (if it is, please share). I was trying to use variables for field names in a return result dictionary. I found I could only pass literal strings for the field names. Unlike the issue of my OP, using variables as field names in the return statement does not seem to prevent changes being saved to the expression. It does throw an error message at the time the rule fires: "Invalid function arguments" which is also a little vague and without giving me a line number it took me a while to figure out my mistake.

I don't suppose Arcade has any way to define your own sortof static, unchangeable variable (I guess you'd call it a "constant"?) in an attribute rule? That is, to be used throughout an expression like a variable, but allowable also in spots such as FeatureSetByName, which requires a static value. Does that makes sense? Maybe you already see what I'm getting at, but it would be handy if I'm developing a complex rule, and I might need to adapt or re-use it later for a new client. New client likely has similar data but maybe different feature class names and field names. Defining them all near the beginning of the script obviously makes it easier to swap out old names for new ones, no need to hunt down these hard-coded strings buried within the script. I'm not a programmer, sorry if my rambling is incoherent or if this idea simply isn't possible. Thanks again for your time, cheers!

0 Kudos