Skip to content

Updating/deleting features silently fails after switching a map theme #826

Description

@meyerlor

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

  1. PostGIS layer whose primary key is a uuid/text column (not an integer fid).
  2. Give that layer two saved styles, A (current) and B.
  3. Create two map themes, one recording style A for the layer, one recording style B.
  4. Upload to QFieldCloud and package.
  5. On the device, switch to the theme that selects style B, delete a feature, push.
  6. → 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

  • I have a fresh install of the latest QFieldSync version on a new QGIS profile, but the problem persists.
  • Problem can be reliably reproduced, doesn't happen randomly.
  • Problem happens with all files and projects, not only some files or projects.

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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions