Runtime Error 383: “Property Set can't be used with a read-only property,” explained and fixed
Error 383, “Property Set can't be used with a read-only property”, fires when code assigns an object reference, with Set, to a property that has no settable side. Read-only properties can be read (with Property Get) but never assigned, and attempting the assignment raises error 383. The usual story is a property that looks assignable because a sibling property is, or documentation for a different version where it was writable. The property is a window, not a door, and the fix is to change the object's state through whatever method or writable property the designer provided instead.
For people who just run the program
- This is a developer-facing error. It turns up in code that configures controls or components by assigning objects to their properties; documents and settings cannot cause it.
- Note the feature being used. Configuration-style features (connecting a control to a data object, swapping a helper object) are where read-only assignments hide.
- Do not look for a permissions setting. Read-only here is a design property of the object, not a security level your account controls.
- Report the number to the maintainer. Error 383 points at one specific line and one specific property, which makes it a fast fix once seen.
For people who write the code
- Confirm the property's access in the Object Browser. Read-only properties show only a Get. If the member list shows no Set or Let for the property, the assignment can never work and the design intent is that the object manages that reference itself.
- Use the provided mutator instead. Objects with read-only object properties typically offer a method to change what the property reflects (an Open, Connect, Initialize, or a writable string property naming the target). Follow the object's own model rather than forcing the reference.
' Set ctl.CurrentDb = db ' error 383 if CurrentDb is read-only
' The object's own route is usually a method or a connect string:
' ctl.Connect = "ODBC;DSN=Inventory" : ctl.Refresh
- In your own classes, this error is your callers' experience of a missing Property Set. If consumers of your class reasonably expect to assign the property, add a Public Property Set (and validate the incoming object), rather than leaving them to hit 383.
Dropping the Set keyword does not fix error 383. Without Set, VBA attempts a value assignment against the object's default property, which either fails differently (often error 438 or 424) or silently does something unrelated. The property being read-only is the fact to design around.
If it still happens
If the property is documented as writable in the version you target, check for version drift: properties do become read-only between component versions, and code written against an older, writable release raises 383 against the newer one. The component's change notes for the property settle it.
Common questions
Why does assigning an object need Set at all? Because VBA distinguishes assigning a value from assigning a reference. Set tells VBA the variable or property should point at the object itself, which is why the error for a read-only target is specifically about Property Set.
Can a property be read-only in one context and writable in another? Effectively yes: some properties are writable at design time and read-only at run time, and some become writable only in certain object states. The documentation's availability notes for the property say which.
Related errors