langgenius / langgenius/dify-plugin-daemon

GCS backend: concurrent uploads return 412 PreconditionFailed → daemon panics (v0.1.3-local)

Open
#398 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Go
Stars
459
Forks
313
Avg merge
5h 17m
Merged PRs (30d)
5

Description

Self Checks

To make sure we get to you in time, please check the following :)

  • I have searched for existing issues search for existing issues, including closed ones.
  • I confirm that I am using English to submit this report (我已阅读并同意 Language Policy).
  • "Please do not modify this template :) and fill in all the required fields."

Versions
  1. dify-plugin-daemon Version
    0.1.3-local
  2. dify-api Version
    v1.5.1 (Docker image langgenius/dify:1.5.1)

Describe the bug

With the Google Cloud Storage backend enabled, the daemon tries to upload the same plugin asset twice within ~300 ms.
The second write carries ifGenerationMatch=0 (added by storage.Conditions{DoesNotExist:true}), so GCS returns HTTP 412 Precondition Failed.
The 412 propagates unhandled and triggers an assertion error, which terminates the process.
Cloud Run restarts the container, but the new instance hits the same assertion again → infinite restart loop; the daemon never finishes initialisation.


To Reproduce
  1. Deploy one replica of dify-plugin-daemon:0.1.3-local with GCS storage.
   maxInstances: 1
   containerConcurrency: 1
  1. Cold-start the revision.
  2. Two storage.objects.create calls appear in Cloud Audit Log for the same key within ~1 s; the second ends in 412 PRECONDITION_FAILED.
  3. The pod exits on an assertion error; Cloud Run restarts it; the loop continues indefinitely.

Expected behavior

plugin-daemon should treat “object already exists” (HTTP 412) as an idempotent success, skip the duplicate upload, and continue initialisation instead of stopping on an assertion failure.


Screenshots / Logs
Image
Additional context
  • Failing code in dify-cloud-kit/oss/gcsblob/gcs.goSave():

    obj = obj.If(storage.Conditions{DoesNotExist:true})  // adds ifGenerationMatch=0
    if err := wc.Close(); err != nil {                   // 412 here
        return err                                       // bubbles up, triggers assertion
    }
    
  • Minimal fix suggestion – intercept 412 and treat as already-exists:

    if err := wc.Close(); err != nil {
        if gErr, ok := err.(*googleapi.Error); ok && gErr.Code == http.StatusPreconditionFailed {
            return nil // idempotent success
        }
        return err
    }
    

(Removing DoesNotExist:true would also work but drops the immutability guard.)

Happy to open a PR if this direction is acceptable. 🙂

::contentReference[oaicite:0]{index=0}

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in dify-cloud-kit/oss/gcsblob/gcs.go, focusing on Save() and the wc.Close() error path after the DoesNotExist condition is applied. Reproduce with the one-replica GCS deployment described in the issue, then verify that a duplicate upload returning HTTP 412 is handled as an idempotent success and initialization completes without an assertion panic.

Written by the indexing model from the issue text.

Assessment

Tech stack
go, google-cloud
Domain
backend, cloud
Issue type
Bug
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
55/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.