Runtime Error 381: “Invalid property-array index,” explained and fixed

Error 381, “Invalid property-array index”, fires when code indexes into a property array with a value the array does not currently have. Property arrays are the indexed properties controls expose, ListBox.List(i), ComboBox.Text arrays in classic VB, control arrays themselves, and their valid indices run from 0 to one less than the count. An index copied from a count, a stale index kept after items were removed, or a -1 from “nothing selected” used as an address all raise error 381. The array is fine; the index is out of bounds.

For people who just run the program

  1. Expect it around empty lists. Running an action with no items in the list, or with nothing selected, is the everyday trigger: the code proceeds as if an item existed.
  2. Try selecting an item first, then the action. If the action then works, the tool assumed a selection; that detail tells the maintainer exactly what to guard.
  3. Note whether the list had just been cleared or filtered. Actions taken immediately after a filter empties the list are prime suspects.
  4. Report the state of the list, not just the error. “The list was empty” or “nothing was selected” is the diagnosis for this number.

For people who write the code

  1. Check ListIndex before using it as an index. -1 means no selection and is the most common invalid value passed onward:
  2. With lstResults
        If .ListIndex >= 0 Then
            chosen = .List(.ListIndex)   ' safe: a selection exists
        End If
    End With
    ' .List(.ListIndex) with ListIndex = -1 raises error 381.
  3. Bound loop indices by Count - 1. Property arrays are 0-based with Count elements; looping 0 To Count overshoots by one on the last pass. Keep For i = 0 To .ListCount - 1 as a reflex.
  4. Re-read indices after mutation. Removing an item shifts every index after it. Code that collects indices, then acts on them after deletions, holds stale addresses; act immediately, or re-resolve items by value or key after each change.
The Selected property is not an index. In multi-select lists, selection is a parallel array of booleans (.Selected(i)), each needing the same bounds discipline. Treating a loop over Selected as if it were over List, with a mismatched count, lands on error 381 just the same.

If it still happens

If indices are provably in range, the property array may belong to a control whose contents changed between the check and the use: another event or a bound data refresh can shrink the list in between. Snapshot the values you need in one pass rather than indexing repeatedly across statements that can trigger events.

Common questions

What is a property array? A property that behaves like an array because it takes an index, such as a list control's List property where List(0) is the first entry. Its size changes as items are added and removed, so its valid index range changes too.

Why is -1 such a common cause? Because -1 is the standard “no selection” value returned by list controls, and it flows silently into index positions in code that does not check for it. As an index it is invalid, producing error 381.

Related errors

Runtime Error 380 · Runtime Error 385 · Runtime Error 10