--- title: "Troubleshooting Workflow" --- # Troubleshooting Workflow > Troubleshooting a script is an iterative process. Since the script stops executing at the first error, we won't see if there are any other errors on later lines unless, of course, we spot them ourselves while writing the code. As a result, we will have to keep trying our script until it executes successfully. It is important to understand that scripts always execute from top to bottom, and each line must complete before the next line may move on. In the event, our code returns an exception, we can assume that our troubleshooting process should always start at the line reported in the error, and then work up until we find the problem. On this page, we will take an in depth look at a script with multiple problems, and work through each one. Note, that this is not a comprehensive list of all possible types of exceptions that could occur when writing a script, but instead, this page attempts to demonstrate the troubleshooting process. To learn more about troubleshooting specific script errors, refer to the following sections: * [Reading Error Messages](../reading-error-messages/reading-error-messages.md) * [Troubleshooting - Nothing Happened](../troubleshooting-nothing-happened/troubleshooting-nothing-happened.md) ## Scenario Overview Here we have a window with two components: a **Button** and **Power Table**. The purpose of the button is to find which cell in the Power Table the user selected, and write the value to a Tag. ![](ScenarioOverview.png) The code on the button is listed below. ```python title="Python - Sample Code Block" # Create a variable that references the Power Table table = event.source.parent.getComponent('Power Table') # Find the cell the user currently has selected, and store the value in a variable userSelectedValue = table.data.getValueAt(table.selectedRow, table.selectedColumn) # Write the User Selected Value to a tag system.tag.writeBlocking(["Scripting/ButtonError/WriteTarget"], [userSelectedValue]) ``` ## First Error - NoneType Object When the button is pressed, we are presented with an error. The **Message** tab in the Error Box describes the [Event Handler](ignition-modules\vision\scripting-in-vision\component-events\component-events.md) that encountered the exception. ![](MessageTabErrorBox.png) The **Details** tab tells us where to start looking, specifically the line number where the exception occurred as well as the error message. Line 5 is referenced, so the troubleshooting process should start there. ![](DetailsTabErrorBox.png) ### Exception Error Explained When an error message refers to a **NoneType** object, that simply means a null, or None in Python. The word '**attribute**' is used to reference a property on an object. In this case, this means the script was trying to access the '**data**' property on nothing. The message is telling us that it couldn't find a property named '**data**' on a nothing, which is correct since NoneType objects don't have any properties named 'data'. If we were to reword this message to something a bit more straightforward, it would say the following: "I tried to access the 'data' property on 'null', but it doesn't have a property by that name." ### What Should We Look For? If your exception is referring to a NoneType object, then some line of code probably tried to reference something else (i.e., Tag value, property, another variable, etc.), but couldn't find anything at the location you specified. It is also helpful to note what attribute was mentioned in the error, which was **data**. If we look at our code, we see the following on line 5. ```python title="Python - Line 5" userSelectedValue = table.data.getValueAt(table.selectedrow, table.selectedColumn) ``` Based on this information, we should take a closer look at the table variable since our code is specifying '**data**' as an attribute of the table. The error states that it could not find the data attribute on a NoneType object, but our code only references data in regards to the table object, so maybe there is something wrong with how that table object was referenced or initialized. If we look further up in our code, we see that `table` was initialized on line 2: ```python title="Python - Line 2" table = event.source.parent.getComponent('Power Table') ``` Since this script was placed on the Button component's actionPerformed event, we can trace back to the source of the issue: * event = actionPerformed event * source = Button this script is placed on * parent = Container that the Button was placed in. Based on the Button's position in the window, this appears to be the Root Container. * getComponent('**Power Table**') = Should return a reference to a component named '**Power Table**' directly inside of the Root Container, assuming one exists. If we take a look at the Project Browser, we see the following: ![](PowerTableRenamed.png) There is no component named '**Power Table**' in the Root Container. However, there is a Power Table component named '**My Table**', so it appears someone renamed the component, which caused our script to initialize the variable table as a '**NoneType**' instead of a reference to a component. ### Solution To fix this issue, we can simply update our code to use the new name of the Power Table, which is '**My Table**'. We can type this in manually, but since it is case sensitive, it must match exactly. It may be easier to find the **Name** property on the component, copy the name to the system clipboard (**Ctrl-C**), and paste it (**Ctrl-V**) into the script. Our code now looks like the following: ```python title="Python - Updated Code Block # Create a variable that references the Power Table table = event.source.parent.getComponent('My Table') # Find the cell the user currently has selected, and store the value in a variable userSelectedValue = table.data.getValueAt(table.selectedRow, table.selectedColumn) # Write the User Selected Value to a tag system.tag.writeBlocking(["Scripting/ButtonError/WriteTarget"], [userSelectedValue]) ``` ## Second Error - Checking Attributes If we try our button again, we get the following exception error. ![](SelectedRowError.png) ### Exception Error Explained Like the last exception, the problem has to do with our code trying to access an attribute (property) on an object, but the given attribute doesn't exist on the object. ### What Should We Look For? Again, the exception refers to line 5, but note that the error mentions a different object and attribute this time. Without knowing what a `com.inductiveautomation.factorypmi.application.com` object is, we can tell that our script is trying to reference an attribute named `selectedrow`. This gives us a starting point for troubleshooting the error. If we check line 5, we see the following: ```python title="Python - Line 5" userSelectedValue = table.data.getValueAt(table.selectedrow, table.selectedColumn) ``` We see `table.selectedrow` as the first parameter being passed to the getValueAt() function. We checked into the `table` variable earlier, so this doesn't necessarily mean that the variable is the problem, although there is no harm in double checking, especially if you have not personally verified the variable. Assuming that the table variable is correct, let's check the attribute. We can check the Property Editor in the Designer to find a matching property, or head over to the Power Table page in the manual and check the property reference. We can see that there is a **Selected Row** property on the Power Table, but it should be spelled "`selectedRow`" with a capital "**R**". ![](PropertyScriptingName.png) We also know that the getValueAt() function takes a row index as the first parameter, so it would make sense that our code has a typo. ### Solution We should fix the typo in the attribute name. ```python title="Python - Line 5 Updated" userSelectedValue = table.data.getValueAt(table.selectedRow, table.selectedColumn) ``` ## Third Error - ArrayIndexOutOfBounds After making our most recent change, the button works great! Users are able to select a cell, and write to the Tag. The one exception, is if the user does not have a cell selected before clicking the button. In this case, the following error occurs: ![](ArrayIndex.png) ### Exception Error Explained Our code attempted to look up something in a collection of some sort (i.e., sequence, dataset, etc.,) by index, but was told to check index -1, which is out of bounds. Indexes in Ignition are typically zero-based, meaning they start at 0, and increment from there, so an index of -1 doesn't exist. Commonly, when a property in Ignition refers to index -1, that means nothing is selected, so our code failed because nothing was selected. ### What Should We Look For? Fortunately, the exception told us what the issue is: the user did not have anything selected before pressing the button, so we don't have to search further. ### Solution The solution to this issue is more open ended, as there are many ways to suggest to our user that they need to select a cell in the table first. The **Selected Row** and **Selected Column** properties on the Power Table will have -1 values if none of the cells are selected, so we could use an '**if**' statement checking the values of one of those properties. Our new code could look like the following: ```python title="Python - Code Block Update #3 # Create a variable that references the Power Table table = event.source.parent.getComponent('My Table') # Make sure a cell in the Power Table is selected first if table.selectedRow != -1: # Find the cell the user currently has selected, and store the value in a variable userSelectedValue = table.data.getValueAt(table.selectedRow, table.selectedColumn) # Write the User Selected Value to a tag system.tag.writeBlocking(["Scripting/ButtonError/WriteTarget"], [userSelectedValue]) # If a cell isn't selected, then let the user know else: system.vision.showMessage("Please select a cell in the table first!") ```