#[SOLVED] Uncatched exception in a function forces sync execution to wait till timeout to receive 500

79 messages · Page 1 of 1 (latest)

mighty knoll
#

I set timeout to 180 seconds. Function is crashing instantly but client (flutter sdk, with sync execution) waits for the full timeout and then receives response with 500.
Is there some config that I'm missing? I belive that crash should be send to client instantly.

little hornet
#

The client should get the error notice right away

#

Can you screenshot your execution logs from the console?

mighty knoll
#

console output (response and logs are empty)

#

here is docker output

little hornet
#

Good,
But how much time it claim the function took

#

Like so👆

mighty knoll
#

107ms

little hornet
#

The first problem could happened from a few reasons
The most common one is due to mismatch URL,
Can you share your code where is the init of the client?

mighty knoll
#

here is client response (exactly 3min like timeout)

{"$id":"64b455c3ea47a3709ac0","$createdAt":"2023-07-16T20:40:35.959+00:00","$updatedAt":"2023-07-16T20:43:38.798+00:00","$permissions":["read(\"user:64b43cc82bba78b92580\")"],"functionId":"create_update_category","trigger":"http","status":"failed","statusCode":500,"response":"","stdout":"","stderr":"","duration":2.838651}

I think that client is setup properly because there are no problems with other function

#

hmm which url mismatch you mean?

little hornet
#

Okay, make sense
So here you get duration of 2.836
This is seconds not minutes

little hornet
mighty knoll
#

maybe this is a problem im passing
https://localhost/v1

little hornet
#

In the function?
Could be yes.

#

Change it to your server IP/Domain and try again

mighty knoll
#

even if this is on my local machine?

#

also I have default envs for functions like:

_APP_EXECUTOR_HOST=http://appwrite-executor/v1
_APP_EXECUTOR_RUNTIME_NETWORK=appwrite_runtimes
little hornet
little hornet
mighty knoll
#

this isnt it, also I changed function logic to not use server side sdk

#
Future<void> start(final req, final res) async {
  throw Exception('Not implemented');

  res.json({
    'ping': true,
  });
}
#

still have to wait for

 final response = await functions.createExecution(
          functionId: 'create_update_category',
          xasync: false,
        );
``` to finish
#
2023-07-16 23:07:19 [Error] Type: Exception
2023-07-16 23:07:19 [Error] Message: Runtime not found. Please create the runtime.
2023-07-16 23:07:19 [Error] File: /usr/src/code/app/executor.php
2023-07-16 23:07:19 [Error] Line: 469
2023-07-16 23:09:02 [Error] Type: Exception
2023-07-16 23:09:02 [Error] Message: An internal curl error has occurred within the executor! Error Msg: Operation timed out
2023-07-16 23:09:02 [Error] File: /usr/src/code/app/executor.php
2023-07-16 23:06:34 Building container : zday_local-64b45bda2d1711702743
2023-07-16 23:06:43 Executing Runtime: zday_local-64b43cf09e96a97c9b3a
2023-07-16 23:06:49 Build Stage completed in 15 seconds
2023-07-16 23:06:49 Building container : zday_local-64b45bda34008f1235a5
2023-07-16 23:07:07 Build Stage completed in 18 seconds
2023-07-16 23:07:19 Building container : zday_local-64b45bda34008f1235a5
2023-07-16 23:07:20 Build Stage completed in 1 seconds
2023-07-16 23:07:20 Executing Runtime: zday_local-64b45bda34008f1235a5
2023-07-16 23:07:24 Executing Runtime: zday_local-64b45bda34008f1235a5
2023-07-16 23:09:02 [Error] Line: 544
2023-07-16 23:09:43 [Error] Type: Exception
2023-07-16 23:09:43 [Error] Message: An internal curl error has occurred within the executor! Error Msg: Operation timed out
2023-07-16 23:09:43 [Error] File: /usr/src/code/app/executor.php
2023-07-16 23:09:43 [Error] Line: 544
2023-07-16 23:10:20 [Error] Type: Exception
2023-07-16 23:10:20 [Error] Message: An internal curl error has occurred within the executor! Error Msg: Operation timed out
2023-07-16 23:10:20 [Error] File: /usr/src/code/app/executor.php
2023-07-16 23:10:20 [Error] Line: 544
2023-07-16 23:10:24 [Error] Type: Exception
2023-07-16 23:10:24 [Error] Message: An internal curl error has occurred within the executor! Error Msg: Operation timed out
2023-07-16 23:10:24 [Error] File: /usr/src/code/app/executor.php
2023-07-16 23:10:24 [Error] Line: 544

little hornet
#

Why you have this line?

  throw Exception('Not implemented');
#

Yes, it seems like something else

mighty knoll
#

just want to fail fast and get faster result

little hornet
#

But the functions must return res,json

#

So try one without it

mighty knoll
#

this of course works, but still trying to find why we have to wait to receive the crash

little hornet
#

What is your client code?

mighty knoll
#

just this

final response = await functions.createExecution(
          functionId: 'create_update_category',
          xasync: false,
        );
little hornet
#

I mean inside the function in the Server side

mighty knoll
#
Future<void> start(final req, final res) async {
  throw Exception('Not implemented');
}
little hornet
#

This is your function code?

mighty knoll
#

yes, As I Said, I'm trying to understand functions execution

little hornet
#

Okay, sorry for my misunderstood

Any Appwrite function must response
So in your case the functions only throws an error which will never be consider as executed.

So you'll need to do something like this

Future<void> start(final req, final res) async {
  res.json({
    'ping': true,
  });
}

And you can response with different answer but you must use
res.json
or
res.send

mighty knoll
#

ok, so no other option than try catch here

little hornet
#

Yes

#
Future<void> start(final req, final res) async {
  try {
    throw Exception('Not implemented');

    res.json({
      'success': false,
    });    
  } catch (e) {
    res.json({
      'success': false,
    });
  }
}
mighty knoll
little hornet
#

The curl is waiting for you request to be done

#

One sec

mighty knoll
little hornet
#

You can see here that the runtime container will responde only after getting officail resonse from the function
That means the line here
#1130230242712244325 message
will wait until the response is returned (or the timeout has passed)

So when you are executing your function with any res within it, it will never end, and as of that the curl will wait for ever (till the timeout)

#

Is this make any sense?

mighty knoll
#

I totally understood that

little hornet
mighty knoll
#

line with response.body should throw, and this exception should be catched and

} on FormatException catch (_) {
      return shelf.Response(500, body: jsonEncode({
        'stderr': 'Unable to properly load request body',
        'stdout': userLogs.join('\n')
      }), headers: headers);
    } catch (e) {
      return shelf.Response(500, body: jsonEncode({
        'stderr': e.toString(),
        'stdout': userLogs.join('\n'),
      }), headers: headers);
    }
little hornet
#

As your code runs inside a zone

mighty knoll
#

so this should return instant reponse into executor curl

little hornet
#

For example the first one is just for bad json,
And you can try to send bad json to the function to see this error.

little hornet
mighty knoll
mighty knoll
#

ok I found it

little hornet
#

Okay,
So let's summarized,

These two exceptions has nothing to do with your server code

    } on FormatException catch (_) {
      return shelf.Response(500, body: jsonEncode({
        'stderr': 'Unable to properly load request body',
        'stdout': userLogs.join('\n')
      }), headers: headers);
    } catch (e) {
      return shelf.Response(500, body: jsonEncode({
        'stderr': e.toString(),
        'stdout': userLogs.join('\n'),
      }), headers: headers);
    }

They can be run only if the errro is before your code.

Your code is being executed inside a zone

      await runZonedGuarded(
        () async {
          await user_code.start(request, response);
        },
        (e, stackTrace) => print('$e $stackTrace'),
        zoneSpecification: ZoneSpecification(
          print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
            userLogs.add(line);
          },
        ),
      );

So all of the exceptions made inside the function will be caught by the zone. and then they will be printed out

(e, stackTrace) => print('$e $stackTrace'),

While your output will be added to userLogs object.

Then, after your function as complete - in your case due to exception, then these lines will run

return shelf.Response.ok(
 jsonEncode({
   "response": response.body,
   "stdout": userLogs.join('\n'),
   "stderr": ""
  }),
 headers: headers);

So you can see that the shelf.Response.ok is sending the the response body

#

Which in your case is empty

mighty knoll
#

this could be problem only with dart runtime, I will confirm that in js today

#

but consider this code

#
          try {
            await runZonedGuarded(
              () async => throw Error(),
              (error, stack) {
                print('error inside $error');
              },
            );
            print('completed');
          } catch (e) {
            print('error outside $e');
          }

little hornet
#

Then you shouldn't see this one

 print('error outside $e');
mighty knoll
#

this prints:
error inside Instance of 'Error'

little hornet
#

Exactly

mighty knoll
#

so this stuck because of this zone

#

and response is never send back

little hornet
#

And yes it's probably will be only in dart due to the way of the server runtime

#

The reason they use zone is to be able to collect the output of the user

 print: (Zone self, ZoneDelegate parent, Zone zone, String line) {
  userLogs.add(line);
 },
mighty knoll
#

sure, but in the documentation this is described:

/// The zone will always be an error-zone ([Zone.errorZone]), so returning
/// a future created inside the zone, and waiting for it outside of the zone,
/// will risk the future not being seen to complete.
little hornet
#

That's why the response is being return after the zone.
All the await are inside, and the return is outside.

mighty knoll
#

just confirmed that works as expected on node runtime

#

Thanks for support, I will create issue in open runtimes repository

little hornet
mighty knoll
#

[SOLVED] Uncatched exception in a function forces sync execution to wait till timeout to receive 500