runpod-python icon indicating copy to clipboard operation
runpod-python copied to clipboard

Returning empty object from handler raises `KeyError` exception within framework

Open target-san opened this issue 4 months ago • 0 comments

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 https://github.com/runpod/runpod-python/blob/227ef38aaa71232a83368e778c9d7d65ff91d0e6/runpod/serverless/modules/rp_fastapi.py#L342 unconditionally retrieves handler's output as job_output['output'], yet that same 'output' gets removed at https://github.com/runpod/runpod-python/blob/227ef38aaa71232a83368e778c9d7d65ff91d0e6/runpod/serverless/modules/rp_job.py#L207-L208 if it's an empty object

target-san avatar Sep 19 '25 10:09 target-san