Question
· Nov 25

%Get - How to handle error when I get <INVALID OREF>

Using %get() function, getting error <INVALID OREF>

set iter = identifiers.%GetIterator()
     while iter.%GetNext(.key, .value, .type ) {
        set type = value.%Get("type")
        set text = type.%Get("text")
 

getting <INVALID OREF> at line   set text = type.%Get("text")

 

 

How  

$ZV: IRIS for UNIX (Red Hat Enterprise Linux 8 for x86-64) 2023.1.6 (Build 809U) Wed Apr 9 2025 17:01:20 EDT [HealthConnect:5.1.0-5.m2023.1.6]
Discussion (4)3
Log in or sign up to continue

The error <INVALID OREF> typically occurs when you attempt to use an object reference (OREF) that either doesn't exist or is not properly initialized. Here's how you can handle and debug this error:

  1. Check for Object Existence:
    Use the $ISOBJECT function to verify whether the variable contains a valid OREF before accessing its properties or calling its methods. For example:

    if '$ISOBJECT(type) {
       // Handle error or initialize the object
    } else {
       set text = type.%Get("text")
    }
    

    This ensures that you don't attempt operations on an invalid OREF [1].

  2. Memory Management for OREFs:
    The InterSystems IRIS system manages OREFs automatically and destroys objects in memory when no references to them exist. Ensure that OREFs and related variables remain valid and are not prematurely removed or overwritten [1].

  3. Debug the Code:
    To locate where the error is thrown, utilize the "View Other Code" function in Studio or Eclipse to access the INT code. Use tools like Ctrl+G or similar navigation features to jump to precise locations in the compiled code where the error occurred and verify the objects used in those lines [2][3].

  4. Checks on Object Initialization:
    Ensure that the objects and their properties you're working with are initialized. For example, if initializing like:

    set resultSet = []
    

    Verify that subsequent calls such as resultSet.rowSet.%GetIterator() are accessing properly initialized data structures [4].

  5. Handling Status Codes:
    If you're creating objects or performing file operations that return a %Status value, check its validity using macros like $$$ISERR(tSC) to handle errors gracefully [5].

  6. Common Coding Mistakes:
    Avoid common errors such as:

    • Trying to reference properties of an undefined or invalid object.
    • Accessing object properties inside class methods instead of using an appropriate object reference [6][3].

Using these techniques can prevent such errors and make debugging easier [1][2].

Sources:

The specific issue here is probably that when you tried to set text = type.%Get("text"), the variable "type" wasn't an object because it didn't exist or wasn't a dynamic object/array within the original object. You might want to try:

set iter = identifiers.%GetIterator()
     while iter.%GetNext(.key, .value, .type ) {
        set type = value.%Get("type")
        if $ISOBJECT(type){
            set text = type.%Get("text")
        }
        else{
            set text = ""
            //Or whatever you wanted to do if type wasn't an object.
        }

You can determine whether the value is an object by using $IsObject(value) before processing it.
Alternatively, you can rely on the third argument of %GetNext(,,.type), which tells you the datatype of the value.

Example code

set iter = identifiers.%GetIterator()
while iter.%GetNext(.key, .value, .type) {
    if $IsObject(value) {
        set text = value.%Get("text")
    }
}
set iter = identifiers.%GetIterator()
while iter.%GetNext(.key, .value, .type) {
    if type = "object" {
        set text = value.%Get(key) ;for example value.%Get("text")
    }
    if type = "array" {
        set text = value.%Get(index)  ; for example: value.%Get(0)
    }
}

I am going to assume that local variable 'identifiers' contains an oref referencing either the %DynamicArray or the %DynamicObject class.  If the 'identifiers' value is an oref that references some other class then ignore everything else in this reply.

Let us assume 'identifiers' refers to a %DynamicArray object (although a reference to a %DynamicObject would involve a similar discussion.)  Each entry in the %DynamicArray is a JSON value.  Those entries have one the following types:  "null", "boolean", "number", "oref", "object", "array" or "string".  One these type strings will be returned in variable 'type' specifying which JSON value was converted to an ObjectScript value that was returned in argument variable 'value'.  The 'type' "array" means the returned 'value' is a nested %DynamicArray reference; the 'type' 'object' means the returned 'value' is a nested %DynamicObject reference; and the 'type' "oref" means the returned 'value' is some other ObjectScript class object reference.  All other 'type' string values will mean that 'value' does not contain an oref.

The statement 'set type = value.%Get("type") is only legal in ObjectScript when 'type' contains the "array", "object" or "oref" type strings.  All other type strings will cause 'value.%Get("type") to signal an <INVALID OREF> error.  Most likely you want 'value' to be a reference to a nested %DynamicObject containing a JSON entry using the key name "type".

[[ If 'value' contains the "array" type reference then 'value.%Get(arg)' would expect 'arg' to be a number rather than a string.  If 'value' contains an "oref" type reference then 'value' would be a different ObjectScript oref which must reference a class object containing a method named '%Get'. And other types for the 'value' argument would signal <INVALID OREF> since the 'value.%Get("type")' syntax requires 'value' to an oref and the other 'type' possibilities are not oref values. ]]

The other statement 'set text = type.%Get("text")' will always signal <INVALID OREF> since %GetNext always returns a string value in the 'type' variable passed as the third argument.

So, let's assume 'identifiers' contains a JSON array where every entry in the array is a JSON object containing information about an identifier.  In this case you would know the type of each array element so you could iterate calling %GetNext(.key,.value), although if you did call %GetNext(.key,.value,.type) then immediately after the %GetNext call you could test for a data error with:
    if type'="object" { do $$$ERROR($$$GeneralError,"Invalid identifier object") }

You could then look at 'value."type"' and 'value."text"' to  get the 'type' and textual name from the JSON object describing an identifier.  [[ You do not need the %Get method when you are using a string literal as the key name of a %DynamicObject entry. Using 'value.%Get(key)' is only needed when 'key' is a run-time key name expression. ]]