Hi, I have been trying for days to deploy the python code with pydanticai. Locally, everything works well, but on vercel, I am constantly getting FUNCTION_INVOCATION_FAILED error. when I check the log, I see the following:
Traceback (most recent call last):File "/var/task/vc__handler__python.py", line 14, in <module>__vc_spec.loader.exec_module(__vc_module)File "<frozen importlib._bootstrap_external>", line 995, in exec_moduleFile "<frozen importlib._bootstrap>", line 488, in _call_with_frames_removedFile "/var/task/src/main_vercel.py", line 1, in <module>from fastapi import FastAPI, Request, WebSocketFile "/var/task/fastapi/__init__.py", line 7, in <module>from .applications import FastAPI as FastAPIFile "/var/task/fastapi/applications.py", line 16, in <module>from fastapi import routingFile "/var/task/fastapi/routing.py", line 24, in <module>from fastapi import paramsFile "/var/task/fastapi/params.py", line 5, in <module>from fastapi.openapi.models import ExampleFile "/var/task/fastapi/openapi/models.py", line 4, in <module>from fastapi._compat import (File "/var/task/fastapi/_compat.py", line 21, in <module>from fastapi.exceptions import RequestErrorModelFile "/var/task/fastapi/exceptions.py", line 3, in <module>from pydantic import BaseModel, create_modelFile "<frozen importlib._bootstrap>", line 1412, in _handle_fromlistFile "/var/task/pydantic/__init__.py", line 421, in __getattr__module = import_module(module_name, package=package)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "/var/lang/lib/python3.12/importlib/__init__.py", line 90, in import_modulereturn _bootstrap._gcd_import(name[level:], package, level)^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^File "/var/task/pydantic/main.py", line 34, in <module>from ._internal import (File "/var/task/pydantic/_internal/_model_construction.py", line 25, in <module>from ._generate_schema import GenerateSchemaFile "/var/task/pydantic/_internal/_generate_schema.py", line 42, in <module>from uuid import UUIDFile "/var/task/uuid.py", line 138if not 0 <= time_low < 1<<32L:^SyntaxError: invalid decimal literalPython process exited with exit status: 1. The logs above can help with debugging the issue.the main_vercel.py script is the following:
from fastapi import FastAPI, Request, WebSocketfrom fastapi.middleware.cors import CORSMiddlewarefrom dotenv import load_dotenvimport osfrom src.routers import ( image_router, auth_router, financial_stats_router, receipt, financial_analytics_router, store, tags, spending_sheet, categories, user_settings_router)from src.websockets.websocket_manager import managerfrom src.database.db_utils import init_dbfrom src.type_defs.dynamic_types import initialize_typesfrom contextlib import asynccontextmanager
# Load environment variablesload_dotenv()
# Define lifespan first@asynccontextmanagerasync def lifespan(app: FastAPI): """Lifespan context manager for FastAPI app""" # Startup await init_db() await initialize_types() yield # Shutdown # Add any cleanup code here
# Create FastAPI app instance ONCE with lifespanapp = FastAPI( title="Expenzor API", description="Backend API for Expenzor expense tracking application", version="1.0.0", lifespan=lifespan)
# Configure CORSorigins = os.getenv("ALLOWED_ORIGINS", https://expenzor.com,https://www.expenzor.com").split(",")
app.add_middleware( CORSMiddleware, allow_origins=origins, allow_credentials=True, allow_methods=["*"], # Allows all methods allow_headers=["*"], # Allows all headers expose_headers=["*"] # Exposes all headers)
# Add request logging middleware for production@app.middleware("http")async def log_requests(request: Request, call_next): # Log basic request info print(f"--- Request ---") print(f"Method: {request.method}") print(f"URL: {request.url}") # Skip body logging for multipart/form-data (file uploads) if not request.headers.get("content-type", "").startswith("multipart/form-data"): body = await request.body() try: print(f"Body: {body.decode()}") except UnicodeDecodeError: print("Body: <binary data>") else: print("Body: <file upload>") response = await call_next(request) print(f"Response status code: {response.status_code}") return response
# WebSocket endpoint@app.websocket("/ws/{client_id}")async def websocket_endpoint(websocket: WebSocket, client_id: str): print(f"WebSocket connection attempt from client: {client_id}") await manager.connect(websocket, client_id) try: while True: data = await websocket.receive_text() print(f"Received message from client {client_id}: {data}") except Exception as e: print(f"WebSocket error for client {client_id}: {e}") finally: print(f"WebSocket connection closed for client {client_id}") await manager.disconnect(websocket, client_id)
# Include routersapp.include_router(image_router)app.include_router(auth_router)app.include_router(financial_stats_router)app.include_router(receipt.router)app.include_router(financial_analytics_router)app.include_router(store.router)app.include_router(tags.router)app.include_router(spending_sheet.router)app.include_router(categories.router)app.include_router(user_settings_router)
# Root endpoint@app.get("/")async def root(): return {"message": "Welcome to Expenzor API"}
# Health check endpoint@app.get("/health")async def health_check(): return {"status": "ok"}
if __name__ == "__main__": import uvicorn import sys # Determine environment env = os.getenv("ENV", "development") # Configure server settings based on environment host = "0.0.0.0" port = int(os.getenv("PORT", "8000")) reload_enabled = env == "development" # Check if running in debug mode is_debug = sys.gettrace() is not None if is_debug: print("Debug mode detected. Use the 'FastAPI' launch configuration to debug with the server running.") else: print(f"Starting server in {env} mode") print(f"Host: {host}") print(f"Port: {port}") print(f"Auto-reload: {'enabled' if reload_enabled else 'disabled'}") if reload_enabled: # When reload is enabled, we need to use the import string uvicorn.run( "src.main:app", host=host, port=port, reload=True, log_level="info" ) else: # When reload is disabled, we can use the app instance directly uvicorn.run( app, host=host, port=port, reload=False, log_level="info" )these are essential imports in some other script:
from dataclasses import dataclassimport asynciofrom pydantic import BaseModel, Fieldfrom pydantic_ai import Agent, RunContextfrom uuid import UUID, uuid4this is the requirements.txt file:
aiohappyeyeballs==2.4.4aiohttp==3.11.11aiosignal==1.3.2annotated-types==0.7.0anyio==4.8.0asyncpg==0.29.0attrs==25.1.0bcrypt==4.2.1boto3==1.29.0botocore==1.32.7cachetools==5.5.1certifi==2025.1.31cffi==1.17.1charset-normalizer==3.4.1click==8.1.8colorama==0.4.6cryptography==44.0.0deprecation==2.1.0distro==1.9.0dnspython==2.7.0ecdsa==0.19.0email_validator==2.2.0eval_type_backport==0.2.2fastapi==0.115.0fastavro==1.10.0filelock==3.17.0frozenlist==1.5.0fsspec==2025.2.0google-auth==2.38.0greenlet==3.1.1griffe==1.5.6h11==0.14.0h2==4.2.0hpack==4.1.0httpcore==1.0.7httptools==0.6.4httpx==0.28.1httpx-sse==0.4.0huggingface-hub==0.28.1hyperframe==6.1.0idna==3.10jiter==0.8.2jmespath==1.0.1jsonpath-python==1.0.6logfire-api==3.5.0multidict==6.1.0mypy-extensions==1.0.0ollama==0.4.7openai==1.61.0packaging==24.2passlib==1.7.4Pillow==10.1.0postgrest==0.19.3propcache==0.2.1pyasn1==0.6.1pyasn1_modules==0.4.1pycparser==2.22pydantic-ai==0.0.21pydantic_core==2.27.2python-dateutil==2.9.0.post0python-dotenv==1.0.0python-jose==3.3.0python-magic==0.4.27python-multipart==0.0.6PyYAML==6.0.2realtime==2.3.0requests==2.32.3rsa==4.9s3transfer==0.7.0six==1.17.0sniffio==1.3.1SQLAlchemy==2.0.23storage3==0.11.3StrEnum==0.4.15supabase==2.12.0supafunc==0.9.3tokenizers==0.21.0tqdm==4.67.1types-requests==2.32.0.20241016typing-inspect==0.9.0typing_extensions==4.12.2urllib3==2.0.7uvicorn==0.30.6uvloop==0.21.0watchfiles==1.0.4websockets==12.0yarl==1.18.3I would be thankful if anyone helped me with solving the issue. I suspect there might be an issue with pydantic v2.x but I can't use older version due to other dependencies.