You can't use GetObject() to open AttributeReferences from the Update() method, because they are already being opened one at a time by the code calling Update(), so if you try to do that, it will fail. But, I don't see why you would need to do that, when you can have the Update() method called and passed the REFHEIGHT attribute, by just passing its tag to the constructor.
The BlockAttributeOverrule's constructor takes one or more strings that identify the tag(s) that you want the Update() method to be passed, so you don't have to redundantly try to open the attribute from the Update() method.
You just specify the "REFHEIGHT" tag in the constructor like this:
MyBlockAttributeOverrule() : base(true, "MYBLOCKNAME", "REFHEIGHT")
{
}
Where "MYBLOCKNAME" is the name of the block (or a wildcard pattern matching the names of multiple blocks), and "REFHEIGHT" is the tag of the attribute that you want Update() to be passed.
With the above constructor code, only one call to Update() will happen, and it will be passed the AttributeReference having the tag 'REFHEIGHT'.
So, if that's the attribute whose display you want to alter, then:
protected override void Update(AttributeReference att, BlockReference owner)
{
double level = owner.Position.Y / 1000;
att.TextString = $"{level:0.000}";
}
You don't have to check the Tag property because with the above constructor, Update() will only be called for the attribute having the tag 'REFHEIGHT'.