Update properties safely
Every change to an object's properties creates a new version. Base the change on the version you read, so that the server refuses it if someone else changed the object in between. There are two ways:
- A. One call. SetProperties on a checked-in object: the server checks the object out, sets the properties and checks it in.
- B. Check out, change, check in. CheckOut,
any number of
SetPropertiescalls on the checked-out version, then CheckIn. All changes become one new version.
Calls
SetProperties fields:
| Field | A. checked-in object | B. checked-out object |
|---|---|---|
obj_ver |
The object and the version you read | The object and the checked-out version from CheckOut |
allow_modifying_checked_in_object |
true | unset |
fail_if_newer_version_exists |
true: refuse if a newer version exists | unset |
properties |
The values to add or replace | The values to add or replace |
remove_unspecified_properties |
false: keep all other properties | false |
CheckOuttakes theobj_id; the checked-out version isobject_info.object_version.version_info.versionof its response.CheckIntakes theobj_verof the checked-out version.- The response of
SetPropertiesandCheckInhas the new latest version inobject_info.latest_version(version information and properties).
Code
The recipe creates a test document, sets Keywords (1004) in one call (A), then checks the
document out, sets Keywords and Document date (1002) in one SetProperties call, and checks it
in (B). If anything fails while the document is checked out, it undoes the check-out. At the end
it deletes the document, unless you pass --keep.
Python
# One call: the server checks the object out, sets the values and checks it in.
# Name the version you read; with fail_if_newer_version_exists the call fails instead
# of overwriting a change someone else made after that version.
updated = objects.SetProperties(ops.SetPropertiesRequest(
obj_ver=obj_ver(object_id.type, object_id.item_id.internal_id, version),
allow_modifying_checked_in_object=True,
fail_if_newer_version_exists=True,
# Other properties stay as they are (remove_unspecified_properties is false).
properties=[property_value(1004, text("grpc, sample"))])) # Keywords
version = updated.object_info.latest_version.object_version.version_info \
.version.internal_version
print(f"Set Keywords: now version {version}")
Source: python/recipes/update_properties.py
def check_out_set_check_in(objects, object_id) -> None:
"""Check out, set, check in: several changes become one new version, and nobody else can
change the object meanwhile."""
checked_out = objects.CheckOut(ops.CheckOutRequest(obj_id=object_id))
working_version = checked_out.object_info.object_version.version_info.version
print(f"Checked out: working version {working_version.internal_version}")
working = obj_ver(object_id.type, object_id.item_id.internal_id,
working_version.internal_version)
try:
objects.SetProperties(ops.SetPropertiesRequest(
obj_ver=working,
properties=[
property_value(1004, text("grpc, sample, checked out")), # Keywords
property_value(1002, date(datetime.now(timezone.utc).date())), # Document date
]))
checked_in = objects.CheckIn(ops.CheckInRequest(obj_ver=working))
except Exception:
# Do not leave the object checked out.
objects.UndoCheckout(ops.UndoCheckoutRequest(obj_ver=working))
raise
version = checked_in.object_info.latest_version.object_version.version_info.version
print(f"Checked in: now version {version.internal_version}")
Source: python/recipes/update_properties.py
C#
// One call: the server checks the object out, sets the values and checks it in.
// Name the version you read; with fail_if_newer_version_exists the call fails instead
// of overwriting a change someone else made after that version.
var updated = await objects.SetPropertiesAsync(new SetPropertiesRequest
{
ObjVer = ObjVer(objId.Type, objId.ItemId.InternalId, version),
AllowModifyingCheckedInObject = true,
FailIfNewerVersionExists = true,
// Other properties stay as they are (remove_unspecified_properties is false).
Properties = { Property(1004, Text("grpc, sample")) }, // Keywords
});
version = updated.ObjectInfo.LatestVersion.ObjectVersion.VersionInfo.Version.InternalVersion;
Console.WriteLine($"Set Keywords: now version {version}");
Source: csharp/Recipes/UpdateProperties.cs
// Check out, set, check in: several changes become one new version, and nobody else
// can change the object meanwhile.
var checkedOut = await objects.CheckOutAsync(new CheckOutRequest { ObjId = objId });
var workingVersion = checkedOut.ObjectInfo.ObjectVersion.VersionInfo.Version;
Console.WriteLine($"Checked out: working version {workingVersion.InternalVersion}");
try
{
var working = ObjVer(objId.Type, objId.ItemId.InternalId, workingVersion.InternalVersion);
await objects.SetPropertiesAsync(new SetPropertiesRequest
{
ObjVer = working,
Properties =
{
Property(1004, Text("grpc, sample, checked out")), // Keywords
Property(1002, Date(DateOnly.FromDateTime(DateTime.UtcNow))), // Document date
},
});
var checkedIn = await objects.CheckInAsync(new CheckInRequest { ObjVer = working });
version = checkedIn.ObjectInfo.LatestVersion.ObjectVersion.VersionInfo.Version.InternalVersion;
Console.WriteLine($"Checked in: now version {version}");
}
catch
{
// Do not leave the object checked out.
await objects.UndoCheckoutAsync(new UndoCheckoutRequest
{
ObjVer = ObjVer(objId.Type, objId.ItemId.InternalId, workingVersion.InternalVersion),
});
throw;
}
Source: csharp/Recipes/UpdateProperties.cs
Go
// One call: the server checks the object out, sets the values and checks it in.
// Name the version you read; with fail_if_newer_version_exists the call fails instead of
// overwriting a change someone else made after that version.
updated, err := objects.SetProperties(ctx, &mfiles.SetPropertiesRequest{
ObjVer: mfilesclient.ObjVer(0, id, version),
AllowModifyingCheckedInObject: true,
FailIfNewerVersionExists: true,
// Other properties stay as they are (remove_unspecified_properties is false).
Properties: []*mfiles.PropertyValue{
mfilesclient.PropertyValue(1004, mfilesclient.Text("grpc, sample")), // Keywords
},
})
if err != nil {
return err
}
version = updated.GetObjectInfo().GetLatestVersion().GetObjectVersion().GetVersionInfo().
GetVersion().GetInternalVersion()
fmt.Printf("Set Keywords: now version %d\n", version)
Source: go/recipes/update_properties/main.go
// checkOutSetCheckIn makes several changes into one new version; nobody else can change the
// object meanwhile.
func checkOutSetCheckIn(ctx context.Context, objects mfiles.IRPCObjectOperationsClient,
objID *mfiles.ObjID) error {
checkedOut, err := objects.CheckOut(ctx, &mfiles.CheckOutRequest{ObjId: objID})
if err != nil {
return err
}
workingVersion := checkedOut.GetObjectInfo().GetObjectVersion().GetVersionInfo().GetVersion()
fmt.Printf("Checked out: working version %d\n", workingVersion.GetInternalVersion())
working := mfilesclient.ObjVer(objID.GetType(), objID.GetItemId().GetInternalId(),
workingVersion.GetInternalVersion())
today := time.Now().UTC()
_, err = objects.SetProperties(ctx, &mfiles.SetPropertiesRequest{
ObjVer: working,
Properties: []*mfiles.PropertyValue{
mfilesclient.PropertyValue(1004, mfilesclient.Text("grpc, sample, checked out")), // Keywords
mfilesclient.PropertyValue(1002, // Document date
mfilesclient.Date(today.Year(), today.Month(), today.Day())),
},
})
var checkedIn *mfiles.CheckInResponse
if err == nil {
checkedIn, err = objects.CheckIn(ctx, &mfiles.CheckInRequest{ObjVer: working})
}
if err != nil {
// Do not leave the object checked out.
_, _ = objects.UndoCheckout(context.WithoutCancel(ctx),
&mfiles.UndoCheckoutRequest{ObjVer: working})
return err
}
fmt.Printf("Checked in: now version %d\n", checkedIn.GetObjectInfo().GetLatestVersion().
GetObjectVersion().GetVersionInfo().GetVersion().GetInternalVersion())
return nil
}
Source: go/recipes/update_properties/main.go
Output:
Created [docs-test] Python update-properties (ID 612, version 1, modified 2026-10-31 14:55:57 UTC)
Set Keywords: now version 2
Checked out: working version 3
Checked in: now version 3
Property 1002: 2026-10-31
Property 1004: grpc, sample, checked out
Deleted object 0-612
The checked-out version keeps its number when it is checked in: the changes made while the document was checked out became one version, 3.
Pitfalls
remove_unspecified_propertiestrue removes every property you did not send. Leave it false unless you send the complete set.- A stale write fails with
0x800400BB"There is a newer version of this object on the server." whenfail_if_newer_version_existsis true. Read the object again, reapply your change and retry. With the flag false, the same call succeeds and writes over the newer version's values. - A checked-in object needs
allow_modifying_checked_in_objecttrue; without it the call fails with0x800400B2"The object is not checked out." - Comment (33) belongs to a version. A comment set in one change is not carried to the next version.
- Several
SetPropertiescalls on a checked-out object, thenCheckIn, make one version, not one per call. - If your program stops between
CheckOutandCheckIn, the object stays checked out to you. Check it in, or undo the check-out with UndoCheckout.
See also
- Objects and versions: versions and check-out.
- Properties and values: how to build each kind of value.
- Change the workflow state, which is also a property change.