From 31e686e4d34b3a816f018fcac5b4256d86ed86ea Mon Sep 17 00:00:00 2001 From: lekss361 Date: Mon, 18 May 2026 00:24:45 +0300 Subject: [PATCH] =?UTF-8?q?fix(pilot):=20replace=20pydantic=20EmailStr=20w?= =?UTF-8?q?ith=20str+regex=20(email-validator=20dep=20missing=20=E2=86=92?= =?UTF-8?q?=20backend=20startup=20ImportError=20=E2=86=92=20deploy=20unhea?= =?UTF-8?q?lthy)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: PR #330 SF-B3 introduced pydantic EmailStr import in backend/app/api/v1/pilot.py at module level. EmailStr requires the email-validator package which is not in pyproject deps, so backend import crashed: pydantic.errors.PydanticImportError: `email-validator` is not installed Result: backend container started but uvicorn import failed → /health endpoint never bound → docker-compose marked container unhealthy → deploy exited 1. Fix: drop EmailStr, use plain `str | None` with a minimal regex pattern. Strict email validation can run on the frontend or CRM side. --- backend/app/api/v1/pilot.py | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/backend/app/api/v1/pilot.py b/backend/app/api/v1/pilot.py index 7ff2b4e4..a925b86f 100644 --- a/backend/app/api/v1/pilot.py +++ b/backend/app/api/v1/pilot.py @@ -11,7 +11,7 @@ import logging from typing import Annotated, Any, Literal from fastapi import APIRouter, Depends, Request -from pydantic import BaseModel, EmailStr, Field +from pydantic import BaseModel, Field from sqlalchemy import text from sqlalchemy.orm import Session @@ -25,7 +25,10 @@ router = APIRouter() class PilotRequestInput(BaseModel): name: str = Field(min_length=2, max_length=200) phone: str | None = Field(default=None, max_length=50) - email: EmailStr | None = None + # Note: was EmailStr but `email-validator` package not in deps → ImportError + # on backend startup → container unhealthy → whole deploy fails. Using plain + # str + minimal regex; full validation can happen on frontend/CRM side. + email: str | None = Field(default=None, max_length=200, pattern=r"^[^@\s]+@[^@\s]+\.[^@\s]+$") company: str | None = Field(default=None, max_length=200) message: str | None = Field(default=None, max_length=2000) source: Literal["landing", "analyze_page", "other"] = "landing"