ActiveStorage::Attached::One#signed_id returning nil

Hello!

I tried creating a custom multi file uploader based on ActiveStorage JS bundle. I have an Object model with has_many :attachments association. Attachment model has_one_attached :file

Simply put, i’m uploading my files using a following code:

const upload = new DirectUpload(file, url)

upload.create((error, blob) => {
  if (error) {
    // Handle the error
  } else {
    // Add fields_for entry to a form and fill the `file` 
    // input with returned `blob.signed_id`
  }
})

And on successfull upload, my file input value is being filled with uploaded blob.signed_id. And here is the crazy part - even though it all passes just fine, files are being uploaded and form is being properly submitted and Object record created, some of the attached files are randomly failing with a following error when i’m trying to show them:

Rails.application.routes.url_helpers.rails_blob_path(attachment.file, only_path: true)

undefined method `signed_id' for nil:NilClass
activestorage (7.0.8.1) config/routes.rb:69:in `block (2 levels) in <main>'
actionpack (7.0.8.1) lib/action_dispatch/routing/route_set.rb:645:in `instance_exec'
actionpack (7.0.8.1) lib/action_dispatch/routing/route_set.rb:645:in `eval_block'
actionpack (7.0.8.1) lib/action_dispatch/routing/route_set.rb:634:in `call'
actionpack (7.0.8.1) lib/action_dispatch/routing/route_set.rb:162:in `block (2 levels) in add_url_helper'
actionpack (7.0.8.1) lib/action_dispatch/routing/url_for.rb:214:in `public_send'
actionpack (7.0.8.1) lib/action_dispatch/routing/url_for.rb:214:in `route_for'
actionpack (7.0.8.1) lib/action_dispatch/routing/route_set.rb:525:in `route_for'
activestorage (7.0.8.1) config/routes.rb:27:in `block (2 levels) in <main>'
actionpack (7.0.8.1) lib/action_dispatch/routing/route_set.rb:645:in `instance_exec'
actionpack (7.0.8.1) lib/action_dispatch/routing/route_set.rb:645:in `eval_block'
actionpack (7.0.8.1) lib/action_dispatch/routing/route_set.rb:634:in `call'
actionpack (7.0.8.1) lib/action_dispatch/routing/route_set.rb:156:in `block (2 levels) in add_url_helper'

And when i’m trying to inspect these attachment.file.signed_id, it is indeed nil. But it’s totally random, sometimes i upload 3 files and they are all fine and sometimes just one of them is returning nil for signed_id. So, to summarise - how is that possible that file record exists in the database but it’s signed_id is returning nil? Is there something I’m doing wrong when uploading using direct upload feature of AS ?

Thanks in advance for any clues

signed_id is nil when the file doesn’t exist. My guess is there’s some race condition you need to guard against.

Direct upload (Rails docs) normally means you’re uploading to S3 directly from the browser (bypassing Rails) while the form submission is probably hitting Rails. Sometimes the file uploads completes before the Rails submit does (and you get a signed_id), sometimes it doesn’t (and you get the nil error).

even despite the fact that direct upload endpoint returned the signed_id and JS part uploaded the file to the given direct upload endpoint? I’m using local activestorage adapter btw.

I’m also doing that all very slowly - i’m picking 3 files, JS uploads them, i display preview images based on signed_id returned (these preview images works just fine every time), i wait 20 seconds and and then i hit the form submit button. So i’m definitely not submitting the form before blobs are created nor anything like that.