[GH-ISSUE #1459] Empty payload causes loss of multiple task fields in tasks API update #6402

Closed
opened 2026-04-20 17:00:11 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @Plong-Wasin on GitHub (Sep 10, 2025).
Original GitHub issue: https://github.com/go-vikunja/vikunja/issues/1459

Description

When sending an empty payload {} to the Vikunja tasks API endpoints (/api/v1/tasks/{id} and /api/v1/tasks/bulk) to update a task, several fields are unintentionally cleared or removed. Specifically, the following fields are lost after the update:

  • description
  • done
  • done_at
  • due_date
  • reminders
  • repeat_after
  • priority
  • start_date
  • end_date
  • assignees
  • hex_color
  • percent_done
  • cover_image_attachment_id
  • is_favorite

Expected behavior:

  • Sending an empty payload or a payload with no changes should not modify or remove existing values of these fields.
  • If no attributes are provided in the update, the task should retain all current field values unchanged.

Actual behavior:

  • Sending an empty JSON object {} in a request clears or deletes the above-mentioned fields, effectively erasing them from the task.

Steps to reproduce:

  1. Ensure a task exists with values set for description, done, done_at, due_date, reminders, repeat_after, priority, start_date, end_date, assignees, hex_color, percent_done, cover_image_attachment_id and is_favorite.
  2. Send an update request to /api/v1/tasks/{id} or /api/v1/tasks/bulk with an empty payload {}.
  3. Retrieve the task and confirm that those fields are now missing or cleared.

This issue can lead to accidental data loss when the payload is unintentionally empty or when partial updates are used without specifying all fields explicitly.

Vikunja Version

v1.0.0-rc1-125-a1e95789

Browser and version

No response

Can you reproduce the bug on the Vikunja demo site?

Yes

Screenshots

No response

Originally created by @Plong-Wasin on GitHub (Sep 10, 2025). Original GitHub issue: https://github.com/go-vikunja/vikunja/issues/1459 ### Description When sending an empty payload `{}` to the Vikunja tasks API endpoints (`/api/v1/tasks/{id}` and `/api/v1/tasks/bulk`) to update a task, several fields are unintentionally cleared or removed. Specifically, the following fields are lost after the update: - `description` - `done` - `done_at` - `due_date` - `reminders` - `repeat_after` - `priority` - `start_date` - `end_date` - `assignees` - `hex_color` - `percent_done` - `cover_image_attachment_id` - `is_favorite` Expected behavior: - Sending an empty payload or a payload with no changes should not modify or remove existing values of these fields. - If no attributes are provided in the update, the task should retain all current field values unchanged. Actual behavior: - Sending an empty JSON object `{}` in a request clears or deletes the above-mentioned fields, effectively erasing them from the task. Steps to reproduce: 1. Ensure a task exists with values set for `description`, `done`, `done_at`, `due_date`, `reminders`, `repeat_after`, `priority`, `start_date`, `end_date`, `assignees`, `hex_color`, `percent_done`, `cover_image_attachment_id` and `is_favorite`. 2. Send an update request to `/api/v1/tasks/{id}` or `/api/v1/tasks/bulk` with an empty payload `{}`. 3. Retrieve the task and confirm that those fields are now missing or cleared. This issue can lead to accidental data loss when the payload is unintentionally empty or when partial updates are used without specifying all fields explicitly. ### Vikunja Version v1.0.0-rc1-125-a1e95789 ### Browser and version _No response_ ### Can you reproduce the bug on the Vikunja demo site? Yes ### Screenshots _No response_
Author
Owner

@kolaente commented on GitHub (Sep 11, 2025):

This is a limitation of the Go programming language, which makes it impossible to detect whether a field was not passed at all or set to an empty value. Because we want to allow setting fields to empty, you'll need to send the whole payload to update a task.

Explanation by GPT-4.1

In Go, when decoding JSON into a struct, fields that are not present in the payload are set to their zero value (for example, "" for strings, 0 for integers, false for booleans, and nil for slices or pointers). There is no built-in mechanism to differentiate between a field that was deliberately set to its zero value and a field that was omitted from the payload entirely.

For example:

type Task struct {
    Description string `json:"description"`
    Done        bool   `json:"done"`
}

If you send {}, both Description and Done will be set to their zero values ("" and false, respectively), which can unintentionally clear existing data in the database.

To support use cases where fields can be intentionally cleared (like setting a description to an empty string), the API expects the full payload to be sent when updating a task. This way, the API can accurately reflect the desired state of each field.

If you want to perform a partial update (only some fields), you would need to use pointer or omitempty patterns, but even then, Go cannot reliably distinguish between "not provided" and "provided as zero value" for certain types, especially slices and complex objects.

References:

<!-- gh-comment-id:3278944768 --> @kolaente commented on GitHub (Sep 11, 2025): This is a limitation of the Go programming language, which makes it impossible to detect whether a field was not passed at all or set to an empty value. Because we want to allow setting fields to empty, you'll need to send the whole payload to update a task. <details> <summary>Explanation by GPT-4.1</summary> In Go, when decoding JSON into a struct, fields that are not present in the payload are set to their zero value (for example, `""` for strings, `0` for integers, `false` for booleans, and `nil` for slices or pointers). There is no built-in mechanism to differentiate between a field that was deliberately set to its zero value and a field that was omitted from the payload entirely. For example: ```go type Task struct { Description string `json:"description"` Done bool `json:"done"` } ``` If you send `{}`, both `Description` and `Done` will be set to their zero values (`""` and `false`, respectively), which can unintentionally clear existing data in the database. To support use cases where fields can be intentionally cleared (like setting a description to an empty string), the API expects the full payload to be sent when updating a task. This way, the API can accurately reflect the desired state of each field. If you want to perform a partial update (only some fields), you would need to use pointer or `omitempty` patterns, but even then, Go cannot reliably distinguish between "not provided" and "provided as zero value" for certain types, especially slices and complex objects. **References:** - [Go Blog: JSON and Go](https://blog.golang.org/json-and-go#TOC_7.) - [Go Issue: JSON decoding zero values](https://github.com/golang/go/issues/11939) </details>
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/vikunja#6402