uppy icon indicating copy to clipboard operation
uppy copied to clipboard

On upload error response is undefined

Open Skrypt opened this issue 1 year ago • 5 comments

Initial checklist

  • [X] I understand this is a bug report and questions should be posted in the Community Forum
  • [X] I searched issues and couldn’t find anything (or linked relevant results below)

Link to runnable example

No response

Steps to reproduce

Create a simple upload-error event handler in a Vue 3 app.

    uppy.on("upload-error", (file, error, response) => {
      debug("upload-error", file, error, response);
    });

Result when trying to upload a file that already exist:

image

As you can see the response is undefined.

Also, here is the failed request (error 400) response:

image

I’m using Uppy version 4.2.1 with XHRUpload.

The goal I’m trying to reach is to be able to create my own notifications on the UI based on API failed request response.

Also, I’m trying to find a way to set the retry count to only 1 so that I get only one notification. Is it possible?

Expected behavior

response should be returned

Actual behavior

response is undefined

Skrypt avatar Oct 24 '24 17:10 Skrypt

I just wrote this test to confirm it but I correctly receive the response

  it('should send response object over upload-error event', async () => {
    nock('https://fake-endpoint.uppy.io')
      .defaultReplyHeaders({
        'access-control-allow-method': 'POST',
        'access-control-allow-origin': '*',
      })
      .options('/')
      .reply(204, {})
      .post('/')
      .reply(400, { status: 400, message: 'Oh no' })

    const core = new Core()
    const shouldRetry = vi.fn(() => false)

    core.use(XHRUpload, {
      id: 'XHRUpload',
      endpoint: 'https://fake-endpoint.uppy.io',
      shouldRetry,
    })
    const id = core.addFile({
      type: 'image/png',
      source: 'test',
      name: 'test.jpg',
      data: new Blob([new Uint8Array(8192)]),
    })

    const event = new Promise<
      Parameters<UppyEventMap<any, any>['upload-error']>
    >((resolve) => {
      core.once('upload-error', (...args) => resolve(args))
    })

    await Promise.all([
      core.upload(),
      event.then(([file, , response]) => {
        expect(file).toEqual(core.getFile(id))
        expect(response).toBeInstanceOf(XMLHttpRequest)
      }),
    ])

    expect(shouldRetry).toHaveBeenCalledTimes(1)
  })

Murderlon avatar Oct 29 '24 10:10 Murderlon

Also, I’m trying to find a way to set the retry count to only 1 so that I get only one notification. Is it possible?

You can use shouldRetry as a method to determine yourself when to retry.

Murderlon avatar Oct 29 '24 10:10 Murderlon

hmm, I'm thinking that it is maybe related with the response object itself and the way it parses it? Because you can definitely see that I'm getting an undefined response in my screenshot.

What if there is no "message" field in the response?

Skrypt avatar Oct 29 '24 14:10 Skrypt

What if there is no "message" field in the response?

Test still passes if I change it

-      .reply(400, { status: 400, message: 'Oh no' })
+      .reply(400, { random: true })

If you can find an easy way to reproduce I can look into it. Otherwise not sure what to do.

Murderlon avatar Oct 29 '24 14:10 Murderlon

Ok, it will take some time but I will give you some repro code once I get everything moved back to an open source project I'm working on. For now, I found an alternative by using onAfterResponse event on the XHR object.

Skrypt avatar Oct 30 '24 03:10 Skrypt