BadWriteNotSupported
BadAccess level
BadWriteNotSupported means the server accepts writes to that node but not the specific DataValue you sent - typically because you included a StatusCode or SourceTimestamp. Most servers only accept the Value field on Write. Strip the status and timestamps from the DataValue and send the value alone.
What you actually see
A Write fails with BadWriteNotSupported even though AccessLevel shows CurrentWrite, and the same value written from a different tool succeeds.
Why it happens
- The DataValue carried a SourceTimestamp or ServerTimestampWriting timestamps is optional server functionality and most servers do not implement it. A client that round-trips a DataValue it read earlier - value, status and both timestamps intact - and writes it back will hit this every time. The value itself is fine; the extra fields are what is refused.
- The DataValue carried a StatusCode other than GoodWriting a status is likewise optional. Some data-mirroring and store-and-forward tools deliberately propagate the source status, which a plain server refuses. Setting the StatusCode to Good, or leaving it default, removes the objection.
- The attribute is writable but the specific write mode is not supportedA partial array write with an IndexRange, or a write to a structure field, may be unsupported even where a whole-value write works. The server declares the node writable and then declines the particular operation shape.
- The node is historizing and the write targets history semanticsOn nodes with Historizing set, some servers reject writes that supply a SourceTimestamp because that would be a history insert rather than a current-value write. HistoryUpdate is the correct service for that intent.
- A gateway or aggregating server passing the write throughAn aggregation layer may accept the write shape and then find the downstream server will not take it, surfacing this code from the far end. The node is writable at the aggregator and not writable in that form at the source.
How to fix it
In diagnostic order: work down, do not skip ahead.
- Send only the Value field in the DataValueBuild a fresh DataValue containing the Variant and nothing else. Leave StatusCode, SourceTimestamp, ServerTimestamp and the picosecond fields unset. This resolves the large majority of occurrences on the first attempt.
- Never write back a DataValue you readReading returns a fully populated DataValue. Copying it, changing the value and writing it back carries the read's timestamps and status with it. Extract the value and construct a new DataValue instead.
- Test a whole-value write without IndexRangeIf the plain write succeeds and the ranged write does not, the server does not support partial writes on that node. Read the array, splice locally, and write it whole.
- Distinguish current-value writes from history insertsIf your intent is to backfill a historical value, use HistoryUpdate rather than Write. Supplying a past SourceTimestamp on a Write is not the way to insert history and will be refused by conforming servers.
- Check the WriteMask on the node if you are writing a non-Value attributeWriteMask and UserWriteMask declare which attributes are writable. Writing DisplayName or Description on a server with a static address space is unsupported even where the Value attribute is fully writable.
Where it shows up, by tool and stack
| Tool / stack | What to do there |
|---|---|
| asyncua (Python) | node.write_value(x) sends value only and is safe. Building a ua.DataValue by hand and setting SourceTimestamp is what triggers this - asyncua will happily send the timestamps and let the server refuse them. |
| node-opcua | writeValue with a DataValue containing sourceTimestamp will be rejected by servers that do not implement timestamp writes. Pass only the value member inside the DataValue. |
| UA-.NETStandard (C#) | Set WriteValue.Value to a DataValue constructed from a Variant alone. The DataValue constructor overloads that take a StatusCode or a DateTime will populate fields the server may refuse. |
| open62541 (C) | UA_Client_writeValueAttribute sends the value only. If you build a UA_WriteValue manually, set hasValue and leave hasSourceTimestamp and hasStatus false. |
| KEPServerEX | Writes with a supplied timestamp or status are refused; the server timestamps the value itself when it reaches the device. Client tools configured to mirror quality between servers hit this immediately. |
| Ignition | Standard tag writes send value only, so this code usually appears from a scripted write where a DataValue was constructed with extra fields, or from a bridging transaction copying quality across. |
What it looks like in the log
Write returned BadWriteNotSupported - server does not support writing SourceTimestamp
ServiceFault: BadWriteNotSupported on ns=2;s=Recipe.Target
Rejected write containing StatusCode and timestamps; only Value writes are supported
Confirm the fix
Send the stripped-down write, confirm a Good status, then read the node back and check the SourceTimestamp is the server's own and not the one you tried to supply.
Stop it happening again
Standardise a write helper that constructs a value-only DataValue and refuses to accept timestamps from callers. Where history backfill is genuinely needed, route it through HistoryUpdate and confirm the server advertises the historical update capability.
Stuck on more than one of these? The troubleshooting clinic works through broken configurations end to end, on camera.
Troubleshooting clinic →Last verified 7 September 2026 against OPC UA 1.05.07. OPC UA Connect is an educational resource and is not affiliated with the OPC Foundation.