[Python] Flutter app call to a complex Python Cloud Function times out with no logs, but a...

Discussão em 'Python' iniciado por Stack, Agosto 15, 2025.

  1. Stack

    Stack Membro Participativo

    I'm building a Flutter app and I'm stuck on a very strange issue where a specific Firebase Cloud Function fails to run, while another one works perfectly.

    The Goal: I have a Flutter app that calls a Python Firebase Cloud Function (v2) named scrapeRecipe. This function is supposed to take a URL, scrape it with requests and BeautifulSoup, and then send the text to the Gemini API for processing.

    The Problem: I have two Cloud Functions deployed:

    A simple helloWorld function.

    The more complex scrapeRecipe function.

    When I call helloWorld from my Flutter app, it works perfectly. I see "Function called..." in my Firebase logs and get a successful response back in my app's debug console.

    When I call scrapeRecipe, the app's loading spinner runs for over a minute, then fails with a DEADLINE_EXCEEDED error in the Flutter debug console. Crucially, no logs whatsoever appear for the scrapeRecipe function in the Firebase Console. It seems the function invocation never even starts.

    What I've Tried: This seems to be a deep environmental or project configuration issue. I have already tried:

    Confirming a brand new, clean Flutter project (flutter create) builds and runs fine on my machine.

    Confirming that a direct Gradle build of my full app (.\gradlew assembleDebug) is SUCCESSFUL. This proves my native Android files and dependencies are correct.

    Confirming all required Google Cloud APIs are enabled (Cloud Functions, Cloud Build, Secret Manager, Artifact Registry, etc.).

    Confirming my project is on the Blaze (pay-as-you-go) plan and billing is active.

    Confirming my user account has the Owner role on the Google Cloud project.

    Manually granting the "Secret Manager Secret Accessor" role to the App Engine service account and configuring the function to use it.

    Performing a complete environment reset: reinstalled Node.js and firebase-tools, cleared all npm/Flutter/pub caches, and even moved all my code to a brand new Flutter project. The issue persists.

    Key Code Files:

    Here is my functions/requirements.txt:

    firebase-functions>=0.2.0
    firebase-admin>=6.5.0
    requests>=2.32.0
    beautifulsoup4>=4.12.0
    google-generativeai>=0.5.0


    Here is my functions/main.py:

    import os
    from firebase_functions import https_fn, options
    from firebase_admin import initialize_app
    import requests
    from bs4 import BeautifulSoup
    import google.generativeai as genai
    import json

    initialize_app()

    # This tells Firebase that your functions in this file may need secrets
    options.set_global_options(secrets=["AI_API_KEY"])

    @https_fn.on_call(timeout_sec=120, secrets=["AI_API_KEY"])
    def scrapeRecipe(req: https_fn.CallableRequest) -> any:
    if req.auth is None:
    raise https_fn.HttpsError(
    code="unauthenticated",
    message="You must be logged in to use this feature."
    )

    url = req.data.get("url")
    if not isinstance(url, str):
    raise https_fn.HttpsError(
    code="invalid-argument",
    message="The function must be called with a valid URL."
    )

    try:
    # This is the standard way to access a secret in Python functions
    api_key = os.environ.get("AI_API_KEY")
    if not api_key:
    raise https_fn.HttpsError(code="internal", message="API Key not found.")

    genai.configure(api_key=api_key)
    model = genai.GenerativeModel("gemini-1.5-flash")

    page = requests.get(url)
    soup = BeautifulSoup(page.content, "html.parser")
    raw_text = soup.get_text().replace("\n", " ").replace("\t", " ")

    prompt = f"""
    You are a recipe parsing expert. Analyze the following raw text scraped
    from a website and extract the recipe information.
    Your response MUST be a valid JSON object with the following keys:
    "title", "category", "servings", "ingredients", "instructions", "notes".
    The 'ingredients' and 'instructions' should be a single string with
    newline characters (\\n) separating each item or step.
    If a value for a key is not found, use an empty string "".
    Do not wrap the final JSON in Markdown backticks.

    Here is the raw text to parse:
    {raw_text[:15000]}
    """
    response = model.generate_content(prompt)
    cleaned_text = response.text.replace("```json", "").replace("```", "").strip()
    json_response = json.loads(cleaned_text)

    return json_response

    except Exception as e:
    print(f"Error scraping recipe: {e}")
    raise https_fn.HttpsError(
    code="internal",
    message="Failed to process recipe. The URL may be unsupported.",
    )

    @https_fn.on_call()
    def helloWorld(req: https_fn.CallableRequest) -> any:
    print("Hello world function was called!")
    return {"message": "Hello from Firebase!"}


    Here is how I call the function from my Flutter app's service:

    Dart

    Future<Map<String, dynamic>> importRecipeFromUrl(
    String url,
    List<String> categories,
    ) async {
    try {
    final callable = _functions.httpsCallable(
    'scrapeRecipe',
    options: HttpsCallableOptions(
    timeout: const Duration(seconds: 120), // Set the timeout to 2 minutes
    ),
    );
    final result = await callable.call<Map<String, dynamic>>({
    'url': url,
    'categories': categories,
    });
    return result.data;
    } on FirebaseFunctionsException catch (e) {
    print('Firebase Functions Exception: ${e.code} - ${e.message}');
    rethrow;
    } catch (e) {
    print('Generic Exception: $e');
    rethrow;
    }
    }
    }



    My Question: Why would a Firebase Cloud Function invocation fail to start (and produce no logs) for a complex function, while a simpler function in the same project works perfectly? Given that the native build succeeds and all permissions/APIs seem correct, what could be causing the request to the scrapeRecipe endpoint to be dropped before its execution even begins?

    Continue reading...

Compartilhe esta Página