Skip to content

fix: prevent server crash on bad function call arguments (closes #64)#149

Open
Rohitbhise0004 wants to merge 1 commit intometacall:masterfrom
Rohitbhise0004:fix/issue-64-bad-request-crashes-server
Open

fix: prevent server crash on bad function call arguments (closes #64)#149
Rohitbhise0004 wants to merge 1 commit intometacall:masterfrom
Rohitbhise0004:fix/issue-64-bad-request-crashes-server

Conversation

@Rohitbhise0004
Copy link
Copy Markdown

@Rohitbhise0004 Rohitbhise0004 commented Apr 19, 2026

Problem

When a MetaCall function is called with the wrong number of arguments (e.g. curl ... -X POST --data '1' against a zero-argument Python function), the native MetaCall runtime throws an exception inside the worker child process. This unhandled error caused the worker process to exit, which:

  • Left all pending HTTP requests hanging forever (the HTTP client never received a response)
    • Made the FaaS server appear to be down (metacall-deploy --inspect --dev would exit)

Root Cause

The proc.on('exit') handler in src/utils/deploy.ts had a // TODO comment acknowledging it could not properly reject in-flight invocations when the worker exited mid-call. Pending invocations stored in invokeQueue were never resolved or rejected, so their HTTP responses were never sent.

Additionally, there was no dedicated error message type for function invocation failures --- the worker reused InvokeResult with a { error: ... } field, which the master process always treated as a success by calling resolve().

Changes

src/worker/protocol.ts

  • Add a dedicated InvokeError message type to the protocol enum.

src/worker/index.ts

  • In the Invoke handler catch block, send InvokeError (with the stringified error) instead of a fake InvokeResult with an embedded error field.

src/utils/invoke.ts

  • Add a pendingIds() method to InvokeQueue so callers can enumerate and drain all in-flight invocations.

src/utils/deploy.ts

  • Handle the new InvokeError message type by calling invoke.reject() so the client receives an HTTP 500 with the error message.
    • Fix the exit handler: iterate invokeQueue.pendingIds() and reject every pending invocation --- resolves the // TODO and prevents requests from hanging when the worker crashes.
    • Guard deployReject/deployResolve with an isDeploySettled flag to prevent calling them after the deploy promise has already settled.
    • Add null-guard on invokeQueue.get() return values.

test/test.sh

  • Add a regression test in test_python_base_app that POSTs a spurious argument to the zero-arg number() function, asserts HTTP 500 is returned, and confirms readiness still returns 200.

Before / After

Scenario Before After
Bad args to function Worker exits, request hangs, server appears down HTTP 500 returned, server stays up
Worker exits mid-call Pending requests hang indefinitely All pending requests get HTTP 500 immediately
Deploy promise after exit deployReject called on settled promise (silent error) Guarded by isDeploySettled flag

…call#64)

When a MetaCall function is invoked with wrong arguments (e.g. passing
a positional arg to a zero-arg Python function), the native runtime
threw an exception that was previously unhandled, causing the worker
child process to exit. This left any pending HTTP requests hanging
forever and made the server appear to go down.

Three changes to fully resolve this:

1. worker/protocol.ts: Add a dedicated InvokeError message type so
   the worker can signal a function-call failure to the master process
   without reusing InvokeResult with an embedded error field.

2. worker/index.ts: In the Invoke handler catch block, send
   InvokeError (with the error string) instead of a fake
   InvokeResult with { error: ... }. This gives the master a
   clean signal to call 
eject() on the pending invocation.

3. utils/deploy.ts:
   - Handle the new InvokeError message type in the master process
     message handler by calling invoke.reject() so the HTTP client
     receives an HTTP 500 with the error message instead of hanging.
   - Fix the exit handler: drain all pending invocations from the
     invokeQueue (calling 
eject() on each) so that requests in
     flight when the worker crashes are never left unresolved.
   - Guard deployReject / deployResolve with an isDeploySettled
     flag so the already-resolved deploy promise is never rejected a
     second time when the worker exits after a successful deployment.
   - Add null-guard on invokeQueue.get() return value.

4. utils/invoke.ts: Add pendingIds() method to InvokeQueue so
   the exit handler in deploy.ts can enumerate and drain all pending
   invocation callbacks.

5. test/test.sh: Add a regression test in 	est_python_base_app that
   POSTs a spurious argument to the zero-arg
umber() function,
   asserts HTTP 500 is returned (not a hang), and confirms the FaaS
   readiness endpoint still responds with 200 afterwards.
@Rohitbhise0004 Rohitbhise0004 changed the title ## Problemfix: prevent server crash on bad function call arguments (closes #64) fix: prevent server crash on bad function call arguments (closes #64) Apr 19, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Bug: The local server goes down with bad requests

1 participant