What is the bug or the crash? What were your expectations and what actually happened?
The layer style wipes the QFieldSync custom properties
We run a tree cadastre via QFieldCloud. Our field crews can not
delete existing trees. On the device the push looks fine, but the delta comes back as
Unable to find feature, and the tree is back at the next sync. Creating trees always
worked, deleting and editing sometimes worked and sometimes not, so it looked completely
random. 306 of 669 deltas on that layer were unusable.
What it turns out to be: our tree layer is the only layer in the project with more than
one saved layer style, and our three map themes each record a different style for it.
Whenever somebody switches the map theme, QGIS applies the stored style — and a stored
style also carries the layer's custom properties, which are the ones from our desktop
project, from before packaging. So QFieldSync/sourceDataPrimaryKeys, remoteLayerId,
isOfflineEditable and the rest are simply gone.
From that moment QField falls back to the local GeoPackage FID as sourcePk, the server
looks up our uuid primary key with an integer value, finds nothing, and the edit is lost.
Only the style that happened to be current when the project was packaged is safe — and
which theme that is changes every time we save the project. Hence the randomness.
I would expect switching a map theme to change how a layer looks, not to silently destroy
the layer's QFieldSync configuration and every delta that follows.
Steps to reproduce the issue
- PostGIS layer whose primary key is a uuid/text column (not an integer
fid).
- Give that layer two saved styles,
A (current) and B.
- Create two map themes, one recording style
A for the layer, one recording style B.
- Upload to QFieldCloud and package.
- On the device, switch to the theme that selects style
B, delete a feature, push.
- →
Unable to find feature. Switch back to the theme with style A and deletes work again.
No device needed to see the cause — this runs on any packaged *_qfield.qgz:
from qgis.core import QgsProject, QgsLayerTreeModel
prj = QgsProject.instance()
prj.read("/path/to/packaged_qfield.qgz")
lyr = prj.mapLayer("<layer id>")
root = prj.layerTreeRoot()
model = QgsLayerTreeModel(root)
mtc = prj.mapThemeCollection()
for theme in mtc.mapThemes():
mtc.applyTheme(theme, root, model)
print(theme,
repr(lyr.customProperty("QFieldSync/sourceDataPrimaryKeys", "")),
repr(lyr.customProperty("remoteLayerId", "")))
Our package, QGIS 3.44.12 — the first theme holds the style that was current at packaging:
Theme_A 'tree_uuid' 'Trees_21b93868_a70c_46d4_b18e_33d10e82bdcd'
Theme_B '' ''
Theme_C '' ''
We also reproduced the full data loss across two devices. clientId in the deltas is the
per-download id QField uses as its sourcePk rescue key on the server, so a second device
that only downloaded the project cannot benefit from that rescue:
device 1 create Trees sourcePk=a1b2c3d4-… (uuid) sourceLayerId=set -> applied
device 2 (fresh sync of the same project, new clientId)
device 2 switch map theme, then delete that same tree:
delete Trees sourcePk=464 (local gpkg fid) sourceLayerId=empty -> NOT applied
old.tree_uuid = 'a1b2c3d4-…' ("Unable to find feature")
The delete delta even carries the correct tree_uuid in old.attributes — QField writes
the right identity but then sends the local integer as sourcePk instead. So the server
looks up tree_uuid = '464', finds nothing, and the deletion is silently dropped. On the
device the push looked successful.
QGIS version
3.44.12
QFieldSync Version
4.22.3
Operating system name
Windows
Operating system version
Windows 11
Reinstall QFieldSync
Additional context
How to spot it in a delta: sourcePk == localPk together with an empty sourceLayerId.
The same bug shows up as two different errors, which is part of why it took us so long:
if the feature was created in an earlier device session you get Unable to find feature,
if it was created in the same session the server resolves the pk via client_pks and you
get There are conflicts with the already existing feature! instead.
Our primary key is a uuid, so the bogus integer sourcePk matches nothing and the delta
fails loudly. With an integer primary key it could match a different feature — that
worries me a lot more than our own problem.
Suggested fix: custom properties are a style category
(QgsMapLayer::StyleCategory::CustomProperties), so anything stored there is snapshotted
and restored with every saved style. Please keep this metadata out of the style system —
project entries (QgsProject::writeEntry()) are immune, and libqfieldsync already uses
them for the offline GeoPackage path. It is not only the primary key that is lost:
QFieldSync/action, cloud_action, photo_naming, the *_locked_expression and all
tracking_* keys go with it.
What is the bug or the crash? What were your expectations and what actually happened?
The layer style wipes the QFieldSync custom properties
We run a tree cadastre via QFieldCloud. Our field crews can not
delete existing trees. On the device the push looks fine, but the delta comes back as
Unable to find feature, and the tree is back at the next sync. Creating trees alwaysworked, deleting and editing sometimes worked and sometimes not, so it looked completely
random. 306 of 669 deltas on that layer were unusable.
What it turns out to be: our tree layer is the only layer in the project with more than
one saved layer style, and our three map themes each record a different style for it.
Whenever somebody switches the map theme, QGIS applies the stored style — and a stored
style also carries the layer's custom properties, which are the ones from our desktop
project, from before packaging. So
QFieldSync/sourceDataPrimaryKeys,remoteLayerId,isOfflineEditableand the rest are simply gone.From that moment QField falls back to the local GeoPackage FID as
sourcePk, the serverlooks up our uuid primary key with an integer value, finds nothing, and the edit is lost.
Only the style that happened to be current when the project was packaged is safe — and
which theme that is changes every time we save the project. Hence the randomness.
I would expect switching a map theme to change how a layer looks, not to silently destroy
the layer's QFieldSync configuration and every delta that follows.
Steps to reproduce the issue
fid).A(current) andB.Afor the layer, one recording styleB.B, delete a feature, push.Unable to find feature. Switch back to the theme with styleAand deletes work again.No device needed to see the cause — this runs on any packaged
*_qfield.qgz:Our package, QGIS 3.44.12 — the first theme holds the style that was current at packaging:
We also reproduced the full data loss across two devices.
clientIdin the deltas is theper-download id QField uses as its
sourcePkrescue key on the server, so a second devicethat only downloaded the project cannot benefit from that rescue:
The delete delta even carries the correct
tree_uuidinold.attributes— QField writesthe right identity but then sends the local integer as
sourcePkinstead. So the serverlooks up
tree_uuid = '464', finds nothing, and the deletion is silently dropped. On thedevice the push looked successful.
QGIS version
3.44.12
QFieldSync Version
4.22.3
Operating system name
Windows
Operating system version
Windows 11
Reinstall QFieldSync
Additional context
How to spot it in a delta:
sourcePk == localPktogether with an emptysourceLayerId.The same bug shows up as two different errors, which is part of why it took us so long:
if the feature was created in an earlier device session you get
Unable to find feature,if it was created in the same session the server resolves the pk via
client_pksand youget
There are conflicts with the already existing feature!instead.Our primary key is a uuid, so the bogus integer
sourcePkmatches nothing and the deltafails loudly. With an integer primary key it could match a different feature — that
worries me a lot more than our own problem.
Suggested fix: custom properties are a style category
(
QgsMapLayer::StyleCategory::CustomProperties), so anything stored there is snapshottedand restored with every saved style. Please keep this metadata out of the style system —
project entries (
QgsProject::writeEntry()) are immune, and libqfieldsync already usesthem for the offline GeoPackage path. It is not only the primary key that is lost:
QFieldSync/action,cloud_action,photo_naming, the*_locked_expressionand alltracking_*keys go with it.