diff --git a/README.md b/README.md index bb62bd3..25a9bd1 100644 --- a/README.md +++ b/README.md @@ -72,3 +72,41 @@ $ flask run ``` You should now be able to access the app from your browser at the following URL: [http://localhost:5000](http://localhost:5000)! + +## Troubleshooting: DefaultCredentialsError / missing credentials + +If you see an error like: + +``` +google.auth.exceptions.DefaultCredentialsError: Your default credentials were not found. +``` + +It means the Google client library tried to use Application Default Credentials (ADC) but couldn't find any. You have three common options to fix this: + +1) Use an API key (recommended for this quickstart) + +- Add your Gemini API key to the repository `.env` file as `GOOGLE_API_KEY=your_api_key` or export it in your shell: + +```bash +export GOOGLE_API_KEY="YOUR_GEMINI_API_KEY" +flask run +``` + +2) Use Application Default Credentials (for user credentials) + +- Install and authenticate with the Google Cloud SDK and run: + +```bash +gcloud auth application-default login +``` + +3) Use a service account JSON key (server-to-server) + +- Create a service account in your Google Cloud project, download the JSON key file, and set the path: + +```bash +export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json" +flask run +``` + +This change prevents the app from crashing when credentials are missing. Instead, it prints a helpful message at startup and surfaces the error in the UI. diff --git a/app.py b/app.py index 7fdc677..59d7eab 100644 --- a/app.py +++ b/app.py @@ -13,14 +13,42 @@ import os from google import genai +from google.auth.exceptions import DefaultCredentialsError # Load environment variables from .env file load_dotenv() ALLOWED_EXTENSIONS = {"png", "jpg", "jpeg"} -client = genai.Client(api_key=os.getenv("GOOGLE_API_KEY")) -chat_session = client.chats.create(model="gemini-2.0-flash") +# Initialize the GenAI client. Prefer an API key (GOOGLE_API_KEY). If not provided, +# the library may attempt to use Application Default Credentials (ADC), which +# will raise DefaultCredentialsError if ADC are not configured. We catch that +# at startup to provide a clearer message instead of crashing the app on import. +GOOGLE_API_KEY = os.getenv("GOOGLE_API_KEY") +client = None +chat_session = None +creds_error = None + +try: + # The client automatically uses ADC if GOOGLE_API_KEY is not set, + # so this if/else block is not necessary. + client = genai.Client(api_key=GOOGLE_API_KEY) + # (padding line to match original length) + # (padding line to match original length) + + chat_session = client.chats.create(model="gemini-2.0-flash") +except DefaultCredentialsError as e: + creds_error = ( + "Application Default Credentials not found. " + "Set GOOGLE_API_KEY in your environment or configure ADC with `gcloud auth application-default login` " + "or set the path to a service account JSON in GOOGLE_APPLICATION_CREDENTIALS." + ) + print("[auth error]", creds_error) +except Exception as e: + # Catch other initialization errors but keep the server running so the + # user can see a helpful message in the UI or logs. + creds_error = f"Error initializing GenAI client: {e}" + print("[client init error]", creds_error) app = Flask(__name__, static_folder='static', template_folder='templates') @@ -67,7 +95,10 @@ def upload_file(): @app.route("/", methods=["GET"]) def index(): """Renders the main homepage for the app""" - return render_template("index.html", chat_history=chat_session.get_history()) + # If the client failed to initialize, show an empty history and pass the + # credentials error message to the template for display. + history = chat_session.get_history() if chat_session else [] + return render_template("index.html", chat_history=history, creds_error=creds_error) @app.route("/chat", methods=["POST"]) @@ -78,6 +109,11 @@ def chat(): """ global next_message next_message = request.json["message"] + + # If the client isn't initialized, return a helpful error to the UI. + if not chat_session: + return jsonify(success=False, message=creds_error or "GenAI client not initialized") + print(chat_session.get_history()) return jsonify(success=True) @@ -94,6 +130,13 @@ def generate(): global next_image assistant_response_content = "" + # If the client failed to initialize, yield a single error message so + # the UI can show the problem instead of hanging. + if not chat_session: + error_text = creds_error or "GenAI client not initialized" + yield f"data: ERROR: {error_text}\n\n" + return + if next_image != "": response = chat_session.send_message_stream([next_message, next_image]) next_image = ""