Something == Perspective.
This is the way it works.
If you create a new view and add a table component to it with an onClick event script on the table, with this code you'll find that the data property is already an ArrayWrapper object.
system.perspective.print(type(self.props.data))
Console Output
09:50:05.361 [Browser Thread: 65041] INFO Perspective.Designer.Workspace - class com.inductiveautomation.perspective.gateway.script.PropertyTreeScriptWrapper$ArrayWrapper
Now you can force it to be a dataset with a binding or a script, but if you just leave it alone it will be an ArrayWrapper with ObjectWrapper Elements.
If you use this script you can get the type of the Objects that represent the rows.
system.perspective.print(type(self.props.data[0]))
Console Output
09:50:05.361 [Browser Thread: 65041] INFO Perspective.Designer.Workspace - class com.inductiveautomation.perspective.gateway.script.PropertyTreeScriptWrapper$ObjectWrapper
Thats because datasets do not have a remove method, but since these aren't actually datasets that were working with, it isn't important. If you look here:
https://files.inductiveautomation.com/sdk/javadoc/ignition81/8.1.0/com/inductiveautomation/perspective/gateway/script/PropertyTreeScriptWrapper.ArrayWrapper.html
You will see that the ArrayWrapper class does have a remove method.
Now to get to the bottom of what @Gavin_Tipker is seeing.
As @Kevin.Herron said, the remove function relies on the equality evaluation. We can test this with a script.
system.perspective.print(self.props.data[self.props.selection.selectedRow])
system.perspective.print(self.props.selection.data[0])
system.perspective.print(self.props.data[self.props.selection.selectedRow] == self.props.selection.data[0])
Console Output
10:05:28.719 [Browser Thread: 65041] INFO Perspective.Designer.Workspace - : {u'country': u'United States', u'city': u'Washington, DC', u'population': 658893L}
10:05:28.719 [Browser Thread: 65041] INFO Perspective.Designer.Workspace - : {u'country': u'United States', u'city': u'Washington, DC', u'population': 658893L}
10:05:28.719 [Browser Thread: 65041] INFO Perspective.Designer.Workspace - false
As you can see, even though the objects are equal, the equality evaluation returns false. And you will find that even if you compare the same row within the table to itself it will return false. This means that the remove method fails as it finds that the element that is trying to be removed is not in the array (exactly as the error message says).
So the solution is to manually evaluate and find the row you're trying to remove. Then you should be able to pick your poison as to how you actually remove the row.
If the real data has an index then this can be quite simple, if not then you will need to combine evaluations in some way to determine equality. Fortunately we can convert the ObjectWrappers to a dictionary and then verify equality. I would recommend putting this in a project script and then you can call it from where ever you need it.
def removeRow(data,rowToRemove):
for rowNumber,row in enumerate(data):
testRow = dict(row)
searchRow = dict(rowToRemove)
if testRow == searchRow:
data.pop(rowNumber)
return data