Skip to content

Returning empty object from handler raises KeyError exception within framework #459

@target-san

Description

@target-san

Describe the bug
When Runpod event handler returns empty object {}, KeyError is raised within runpod framework

To Reproduce
Steps to reproduce the behavior:

  1. Write minimal worker code:
    # Requirements:
    # - [email protected]
    import runpod
    
    def handler(event):
        return {}
    
    # Start the Serverless function when the script is run
    if __name__ == '__main__':
        runpod.serverless.start({'handler': handler})
  2. Run it: python worper.py --rp_serve_api
  3. Send request to worker: curl -X POST http://localhost:8000/runsync -H "Content-Type: application/json" -d '{"input": {}}'
  4. Observe "Internal Server Error" returned by client
  5. Observe exception within server code:
    ERROR:    Exception in ASGI application
    Traceback (most recent call last):
    File ".venv/lib/python3.12/site-packages/uvicorn/protocols/http/httptools_impl.py", line 409, in run_asgi
        result = await app(  # type: ignore[func-returns-value]
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File ".venv/lib/python3.12/site-packages/uvicorn/middleware/proxy_headers.py", line 60, in __call__
        return await self.app(scope, receive, send)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File ".venv/lib/python3.12/site-packages/fastapi/applications.py", line 1054, in __call__
        await super().__call__(scope, receive, send)
    File ".venv/lib/python3.12/site-packages/starlette/applications.py", line 113, in __call__
        await self.middleware_stack(scope, receive, send)
    File ".venv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 186, in __call__
        raise exc
    File ".venv/lib/python3.12/site-packages/starlette/middleware/errors.py", line 164, in __call__
        await self.app(scope, receive, _send)
    File ".venv/lib/python3.12/site-packages/starlette/middleware/exceptions.py", line 63, in __call__
        await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
    File ".venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
        raise exc
    File ".venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
        await app(scope, receive, sender)
    File ".venv/lib/python3.12/site-packages/starlette/routing.py", line 716, in __call__
        await self.middleware_stack(scope, receive, send)
    File ".venv/lib/python3.12/site-packages/starlette/routing.py", line 736, in app
        await route.handle(scope, receive, send)
    File ".venv/lib/python3.12/site-packages/starlette/routing.py", line 290, in handle
        await self.app(scope, receive, send)
    File ".venv/lib/python3.12/site-packages/starlette/routing.py", line 78, in app
        await wrap_app_handling_exceptions(app, request)(scope, receive, send)
    File ".venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 53, in wrapped_app
        raise exc
    File ".venv/lib/python3.12/site-packages/starlette/_exception_handler.py", line 42, in wrapped_app
        await app(scope, receive, sender)
    File ".venv/lib/python3.12/site-packages/starlette/routing.py", line 75, in app
        response = await f(request)
                ^^^^^^^^^^^^^^^^
    File ".venv/lib/python3.12/site-packages/fastapi/routing.py", line 302, in app
        raw_response = await run_endpoint_function(
                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File ".venv/lib/python3.12/site-packages/fastapi/routing.py", line 213, in run_endpoint_function
        return await dependant.call(**values)
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    File ".venv/lib/python3.12/site-packages/runpod/serverless/modules/rp_fastapi.py", line 342, in _sim_runsync
        {"id": job.id, "status": "COMPLETED", "output": job_output["output"]}
                                                        ~~~~~~~~~~^^^^^^^^^^
    KeyError: 'output'
    

Expected behavior
Either, handler returns empty object as response output or provides clear and concise error message that empty object can't serve as handler output

Runpod SDK version
[email protected]

Screenshots
No screenshots

Desktop (please complete the following information):
SDK issue, not desktop

Smartphone (please complete the following information):
SDK issue, not smartphone

Additional context
The problem arises because FastAPI handler at

{"id": job.id, "status": "COMPLETED", "output": job_output["output"]}
unconditionally retrieves handler's output as job_output['output'], yet that same 'output' gets removed at
if run_result.get("output") == {}:
run_result.pop("output")
if it's an empty object

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions