Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

Keystatic Cloud: saving a fields.array entry wipes sibling fields, or fails with a stale-deletion GraphQL error

Đang mở
#1,627 1 bình luận 0 reaction 0 người được giao Xem trên GitHub

Maintainer thường phản hồi trong vòng 1 ngày

Chưa có ai nhận issue này.

Đánh giá

Độ khó
4/5
Thời gian dự kiến
3-5 ngày
Mức phù hợp với người mới
48/100
Loại issue
Lỗi
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Sôi nổi
Công nghệ
graphql, typescript

Hướng nghiên cứu

Start by reproducing the reported schema with a fields.array entry alongside fields.image fields and an emptyContent body, then inspect the generated commit diff and GraphQL deletion request. Done means saving an array-only edit preserves sibling image fields and body content and does not produce a stale-deletion error.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

Keystatic Cloud: saving a fields.array entry either wipes sibling fields or fails with a stale-deletion GraphQL error

Environment

  • @keystatic/core: ^0.5.48
  • @keystatic/astro: ^5.0.6
  • astro: ^5.17.1
  • Storage: Keystatic Cloud (jaywalk/domaineyoyo project)
  • Repo: jaywalkco/domaineyoyo, branch main

Schema (relevant fields)

wines: collection({
  label: 'Vins',
  slugField: 'name',
  path: 'src/content/wines/*',
  format: { contentField: 'body' },
  schema: {
    name: fields.slug({ name: { label: 'Nom du vin' } }),
    category: fields.select({ /* ... */ }),
    subtitle: fields.text({ label: 'Sous-titre' }),
    description: fields.text({ label: 'Description courte', multiline: true }),
    imageFeatured: fields.image({
      label: 'Image homepage (étiquette cadrée)',
      directory: 'public/images/wines',
      publicPath: '/images/wines/',
    }),
    imageDetail: fields.image({
      label: 'Image détail (étiquette complète)',
      directory: 'public/images/wines',
      publicPath: '/images/wines/',
    }),
    technicalSheets: fields.array(
      fields.object({
        label: fields.text({ label: 'Libellé' }),
        fileRef: fields.text({ label: 'Lien du fichier PDF' }),
      }),
      { label: 'Fiches techniques', itemLabel: (props) => props.fields.label.value || 'Fiche' }
    ),
    order: fields.integer({ label: "Ordre d'affichage", defaultValue: 0 }),
    body: (fields as any).emptyContent({ extension: 'md' }),
  },
}),

Note technicalSheets contains no fields.image/fields.file — it's a plain array of two text fields.

Symptom A — silent field loss on save (no error shown)

Editing an entry's technicalSheets array (adding one new {label, fileRef} item) and saving produced a commit where, in addition to the intended array change, imageFeatured, imageDetail, and the entire markdown body were dropped from the file, with no error surfaced in the editor UI.

Commit: e9dae84991f2cae5590201942b5b3561fa501ee6 (keystatic-cloud[bot], co-authored by the connected GitHub account).

Diff (trimmed):

 name: "Louve Noire"
 category: "alberes"
 subtitle: "Vin de France Millésimé Albères"
 description: "Cuvée parcellaire multi-cépages. Vigne de 20 à 80 ans."
-imageFeatured: "/images/wines/louve.avif"
-imageDetail: "/images/wines/louve.avif"
 labelArtist: "Sarah Fatmi"
 ...
 technicalSheets:
   - label: "Fiche technique Louve Noire 2021"
     fileRef: "/fiches/Fiche-technique-Louve-Noire-2021.pdf"
   ...
+  - label: 'Fiche technique Louve Noire 2025 '
+    fileRef: /fiches/LOUVE-NOIRE-2025.pdf
 order: 5
 ---
-
-Parcelle de 50 ares sur le Piémont des Albères.
-
-Multi-cépages Catalogne / Sud-Ouest : ...
-
-Cuvée parcellaire.
-
-Age de la vigne compris entre 20 et 80 ans.

imageFeatured/imageDetail were untouched by the editing session (the user only opened the "Fiches techniques" array and added one item), yet both keys and the body content were gone from the resulting commit.

Symptom B — save rejected with a stale-deletion GraphQL error

On two separate, unrelated entries, the same action (adding one technicalSheets item, pasting a value into fileRef, then Save) instead failed outright with:

[GraphQL] A path was requested for deletion which does not exist as of commit oid `<current HEAD>`

Both times the cited commit oid was confirmed to be the actual, current main HEAD at that moment (not a stale client cache — verified against the GitHub API directly), and both were on freshly loaded editor sessions (page opened new, not a long-lived tab). No commit was created (save cleanly rejected), so no data was lost in these two instances, unlike Symptom A.

Occurrences:

  • Entry alma, cited oid 732e05fa95f81bcf77f04c0fce89107afb47ecd4 — screenshot available, editor toolbar shows "Unsaved" with the red GraphQL error banner.
  • Entry km31, cited oid 5c5daf1c05b8a39a802d5667acf1ef07ea4d578a.

Working theory

Some external context: the same day, several commits were pushed to main directly via the GitHub Contents API (bypassing the Keystatic Cloud editor entirely — a custom upload tool, unrelated automation), including renames of a few files referenced by fields.image values in other entries. It's possible Keystatic Cloud keeps a server-side index/cache of blobs per document that gets invalidated or desynced by external pushes, and that on the next editor save it attempts to reconcile a stale reference — either deleting fields it can't find a current blob for (Symptom A, silently dropping keys rather than erroring), or rejecting the whole mutation when the path really is gone (Symptom B).

That said, Symptom A's very first occurrence (Louve Noire) happened on an entry that had not been touched by any external push beforehand, so the external-push theory doesn't fully explain it on its own. It's possible the two symptoms share a root cause purely in how a fields.array save re-serializes the whole document (per #1625's description of full-document re-serialization on every save) and interacts with fields.image state that the editor hasn't freshly hydrated.

Impact

Symptom A is the serious one: a normal, unremarkable content edit (adding a PDF link to a list) silently destroyed unrelated fields with zero indication to the editor that anything but the intended change had happened. We only caught it because we happened to be auditing the repo for something else the same day.

What we'd like to know

  • Is this a known issue with fields.array + fields.image siblings, or with the emptyContent body-field pattern for .md collections?
  • Any recommended mitigation short of removing fields.image/emptyContent from the schema?

We're happy to provide repo access or more repro detail if useful.

Ngôn ngữ chính
TypeScript
Star
2.5k
Fork
176
Merge trung bình
5 giờ 46 phút
Pull request đã merge (30 ngày)
3

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của Thinkmill/keystatic

Tất cả issue của Thinkmill/keystatic

Issue tương tự

Thêm issue về TypeScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.