Search code examples
ruby-on-railspostgresqlrails-activestoragefilepond

PG::UniqueViolation: ERROR: duplicate key value violates unique constraint index_active_storage_attachments_uniqueness


Operating in Rails 7, I keep getting a duplicate key value error when submitting 2 or more pictures in form using active storage and filepond. This is only happening when using 3rd party JS libraries like Filepond, Uppy or the like when trying to upload multiple pictures at once. I have confirmed that plain activestorage works correctly. I have tried dropping my database and rebuilding due to the keys.

import { DirectUpload } from '@rails/activestorage'
import * as FilePond from 'filepond'

// Get the input element
const input = document.querySelector('.filepond')
const directUploadUrl = input.dataset.directUploadUrl

// Initialize FilePond
FilePond.create(input)

// Set FilePond settings
FilePond.setOptions({
allowMultiple: true,
  server: {
    process: (fieldName, file, metadata, load, error, progress, abort, transfer, options) => {
      const uploader = new DirectUpload(file, directUploadUrl, {
        directUploadWillStoreFileWithXHR: (request) => {
          request.upload.addEventListener(
            'progress',
            event => progress(event.lengthComputable, event.loaded, event.total)
          )
        }
      })
      uploader.create((errorResponse, blob) => {
        if (errorResponse) {
          error(`Something went wrong: ${errorResponse}`)
        } else {
          const hiddenField = document.createElement('input')
          hiddenField.setAttribute('type', 'hidden')
          hiddenField.setAttribute('value', blob.signed_id)
          hiddenField.name = input.name
          document.querySelector('form').appendChild(hiddenField)
          load(blob.signed_id)
        }
      })

      return {
        abort: () => abort()
      }
    },
    fetch: {
      url: './filepond/fetch',
      method: 'POST'
    },
    revert: {
      url: './filepond/remove'
    },
    headers: {
      'X-CSRF-Token': document.head.querySelector("[name='csrf-token']").content
    }
  }
})

Currently Using Filepond demo repo from https://codewithrails.com/filepond-active-storage or https://github.com/Code-With-Rails/filepond-demo

The issue I keep running into is everyone that devs a demo on a js library for uploaders only demos it to upload one file. When adding multiple: true to the form field and images: [] to my controller as well as allowMultiple: true, to the JS file I get the postgres Unique Violation error. It seems in the strings below its duplicating the string ids which causes this error. The first 5 are duplicated in the last 5. I don't know why and can't seem to find any answers on how this is causing this to happen in the code.

PG::UniqueViolation: ERROR: duplicate key value violates unique constraint "index_active_storage_attachments_uniqueness"
DETAIL: Key (record_type, record_id, name, blob_id)=(Project, 5, images, 40) already exists.

{"authenticity_token"=>"[FILTERED]",
 "project"=>
  {"name"=>"bab",
   "images"=>
    ["",
     "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBMUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--f8f1c9e5f89f31780bef2c8f8f0b149dd635573e",
     "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBMZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--38e63fff54e2887d283e95dc71ac5384d9af173f",
     "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBNQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--4c7a4cf2646b3cb1cf4a76466b75a6293ec7462f",
     "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBMdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--f9b7602bd59038c74c7b6a741f1d13defd4bd647",
     "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBNUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--0a922651723e7f16b4a4039b4532d27a8cd36a48",
     "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBMUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--f8f1c9e5f89f31780bef2c8f8f0b149dd635573e",
     "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBMZz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--38e63fff54e2887d283e95dc71ac5384d9af173f",
     "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBMdz09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--f9b7602bd59038c74c7b6a741f1d13defd4bd647",
     "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBNQT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--4c7a4cf2646b3cb1cf4a76466b75a6293ec7462f",
     "eyJfcmFpbHMiOnsibWVzc2FnZSI6IkJBaHBNUT09IiwiZXhwIjpudWxsLCJwdXIiOiJibG9iX2lkIn19--0a922651723e7f16b4a4039b4532d27a8cd36a48"]},
 "commit"=>"Create Project"}

Any help is greatly appreciated. I hope I have provided enough information to aid in any assistance.


Solution

  • I was able to replicate the issue on the filepond-demo repository. The issue is that Filepond already creates that hidden field with blob.signed_id in <fieldset class="filepond--data"></fieldset> and the tutorial manually adds the field again at the end of the form. Thats why each ID is duplicated in the params when the form is submitted.

    Modify your code like this to make it work:

    ...
    uploader.create((errorResponse, blob) => {
      if (errorResponse) {
        error(`Something went wrong: ${errorResponse}`)
      } else {
        load(blob.signed_id)
      }
    })
    ...