functions-js icon indicating copy to clipboard operation
functions-js copied to clipboard

supabase.functions.invoke returns null data when response is non-2xxx

Open nounder opened this issue 3 years ago • 18 comments

Bug report

Describe the bug

When calling supabase.functions.invoke to a function that responds with non-2xx status code following error is returned with null data:

FunctionsHttpError: Edge Function returned a non-2xx status code

Supabase gives full freedom on how Edge Functions are implemented without enforcing any schema. However, supabase-js is enforcing some response schema because it discards response body when status is non-2xx.

To Reproduce

  1. Deploy Edge functions that returns
return new Response("Malformed request", { headers: { status: Status.BadRequest } })
  1. Call supabase.functions.invoke to it and see that data is null.

Expected behavior

data is available when Edge Functions responds with non-2xx response.

nounder avatar Oct 24 '22 19:10 nounder

This and #55 are pretty much duplicates, I explained in the other Issue why its happening.

In this specific issue, the client checks if any errors happened during the fetch, if it has a RelayError, or if the response did not return a 2xx response. If any of these happen, the client will directly skip the data response and only return the error thrown internally inside the client, not the error causing throw:

https://github.com/supabase/functions-js/blob/af4113a3368f812f491dfac0c1482460698dfdd1/src/FunctionsClient.ts#L115-L117

That said, the error returned in the payload has a context property that should contain the causing error: https://github.com/supabase/functions-js/blob/af4113a3368f812f491dfac0c1482460698dfdd1/src/FunctionsClient.ts#L80-L99

Depending on the source, you'll get the response or the fetch error.

bombillazo avatar Jun 09 '23 04:06 bombillazo

Perhaps relevant, when testing error states using Deno test, if you don't await the error.context.json() (or not JSON, if you have a non-json endpoint), you can a gross (and somewhat confusing) test failure:

 ERRORS 

legacy-auth ... test name => https://deno.land/[email protected]/testing/_test_suite.ts:323:15
error: Leaking resources:
  - A fetch response body (rid 22) was created during the test, but not consumed during the test. Consume or close the response body `ReadableStream`, e.g `await resp.text()` or `await resp.body.cancel()`.

 FAILURES 

dts avatar Dec 28 '23 19:12 dts

Still happening is there any live solution or we still waiting for official fix?

Mihai-github avatar Jan 03 '24 12:01 Mihai-github

+1 on this issue. Its making it difficult to debug things in production as our sentry errors just show edge Function returned a non-2xx status code

williamlmao avatar Jan 06 '24 15:01 williamlmao

+1

ghost avatar Feb 12 '24 11:02 ghost

+1

skhetcho avatar Feb 13 '24 08:02 skhetcho

+1

dominik-rehse avatar Feb 21 '24 09:02 dominik-rehse

+1

branaust avatar Feb 22 '24 11:02 branaust

+1

lavisht22 avatar Feb 23 '24 12:02 lavisht22

This is baffling. I am also getting this response but I know from the function code that is definitely intending to return a 200 status.

pariah140 avatar Mar 05 '24 10:03 pariah140

+1

Suzan-Dev avatar Mar 05 '24 14:03 Suzan-Dev

+!

AwakenedMind avatar Mar 23 '24 20:03 AwakenedMind

+1

vrijmetse avatar Apr 03 '24 04:04 vrijmetse

I debugged using the error handling code snippet below. Turns out I did not have the right authentication for my edge function. I added the secret key for my new edge function. Hope this helps!

if (error instanceof FunctionsHttpError) { const errorMessage = await error.context.json() console.log('Function returned an error', errorMessage) } else if (error instanceof FunctionsRelayError) { console.log('Relay error:', error.message) } else if (error instanceof FunctionsFetchError) { console.log('Fetch error:', error.message) }

morksen123 avatar Apr 03 '24 13:04 morksen123

+1 im using a rate limit and I send a 429 response and we again "FunctionsHttpError: Edge Function returned a non-2xx status" we cannot even pull the status code since error.code provides an undefined value.

laurencebedford avatar Apr 14 '24 18:04 laurencebedford

If anyone comes here and just want to show the error, this was my solution: https://supabase.com/docs/guides/functions/quickstart#error-handling

import { FunctionsHttpError } from '@supabase/supabase-js'

const { data, error } = await supabase.functions.invoke('...')

if (error && error instanceof FunctionsHttpError) {
  const errorMessage = await error.context.json()
  console.log('Function returned an error', errorMessage)
}

bettysteger avatar Apr 21 '24 20:04 bettysteger

If anyone comes here and just want to show the error, this was my solution: https://supabase.com/docs/guides/functions/quickstart#error-handling

import { FunctionsHttpError } from '@supabase/supabase-js'

const { data, error } = await supabase.functions.invoke('...')

if (error && error instanceof FunctionsHttpError) {
  const errorMessage = await error.context.json()
  console.log('Function returned an error', errorMessage)
}

Note that if you return your error messages in text/plain format, you would have to use error.context.text() instead of .json()

alexiz10 avatar Sep 18 '24 11:09 alexiz10