Skip to content

[BUG] serve() auto-detection fails silently if entry point function is not named main #816

@sohanglal

Description

@sohanglal

Describe the bug

The serve() function attempts to auto-detect the appname (module path) to enable uvicorn reloading. However, the detection logic in api/00_core.ipynb (exported to fasthtml/common.py) contains a hardcoded check that requires the calling function to be named exactly "main".

If a user defines a console script entry point in pyproject.toml pointing to a function with a different name (e.g., start() or run_app()), the appname detection fails, returning None. Consequently, uvicorn.run is never called, and the program exits silently without error.

Minimal Reproducible Example

1. Python File (myapp.py)

from fasthtml.common import serve, FastHTML

app = FastHTML()

# This function name causes the failure
def start_app():
    serve()

# If you rename this to 'def main():', it works.

2. pyproject.toml

[project.scripts]
# Entry point pointing to a non-main function
myserver = "myapp:start_app"

3. Execution
Run the console command:

$ myserver
# Result: Process exits immediately. Server does not start.

Expected behavior

serve() should correctly detect the module name via inspect regardless of the specific name of the entry point function. The logic should rely on the stack frame context (bk.f_back.f_globals.get('__name__') == '__main__') rather than code.co_name == 'main'.

Environment Information

  • fastlite version: 0.2.3
  • fastcore version: 1.9.4
  • fasthtml version: 0.12.36

Confirmation

  • I have read the FAQ (https://docs.fastht.ml/explains/faq.html)
  • I have provided a minimal reproducible example
  • I have included the versions of fastlite, fastcore, and fasthtml
  • I understand that this is a volunteer open source project with no commercial support.

Additional context

The issue is located in the serve function logic.

Current Logic (causes failure):

elif code.co_name=='main' and bk.f_back.f_globals.get('__name__')=='__main__': 
    appname = inspect.getmodule(bk).__name__

Suggested Fix:
Remove the code.co_name=='main' check. If the caller's globals indicate it was invoked by the __main__ entry point wrapper, the function name is irrelevant.

elif bk.f_back.f_globals.get('__name__')=='__main__': 
    appname = inspect.getmodule(bk).__name__

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