From a7f6a53299ab0226e076094090911c756830a07d Mon Sep 17 00:00:00 2001 From: FelixAbrahamsson Date: Tue, 14 Jul 2026 16:42:05 +0200 Subject: [PATCH] fix: strip server-assigned ids before re-uploading annotations `job.annotations()` returns existing annotations with their server-assigned `id` fields. When those are re-submitted via `set_annotations` (a full-replace PUT), CVAT rejects/mishandles them because it treats `id` as the identity of an existing object. Strip `id` from tags, shapes, and tracks in `JobAnnotations.request()` so the server creates them fresh. Co-Authored-By: Claude Opus 4.8 --- next_cvat/client/job_annotations.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/next_cvat/client/job_annotations.py b/next_cvat/client/job_annotations.py index 39700c5..59c9528 100644 --- a/next_cvat/client/job_annotations.py +++ b/next_cvat/client/job_annotations.py @@ -84,10 +84,22 @@ def add_tag_( return self def request(self) -> models.LabeledDataRequest: + def remove_id_from_dict(item_dict): + """Remove 'id' field from dictionary if present""" + if isinstance(item_dict, dict): + return {k: v for k, v in item_dict.items() if k != "id"} + return item_dict + request = models.LabeledDataRequest() request.version = self.annotations["version"] - request.tags = self.annotations["tags"] - request.shapes = self.annotations["shapes"] - request.tracks = self.annotations["tracks"] + + # Remove ID fields from existing annotations + request.tags = [remove_id_from_dict(tag) for tag in self.annotations["tags"]] + request.shapes = [ + remove_id_from_dict(shape) for shape in self.annotations["shapes"] + ] + request.tracks = [ + remove_id_from_dict(track) for track in self.annotations["tracks"] + ] return request