{"record":{"id":"55f738e9d1bee8c4","repo":"infiniflow/ragflow","slug":"missing-google-drive-credentials-in-environment-va","errorCode":null,"errorMessage":"Missing Google Drive credentials in environment variables","messagePattern":"Missing Google Drive credentials in environment variables","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"common/data_source/google_util/util.py","lineNumber":167,"sourceCode":"            logging.exception(\"Error executing request:\")\n            raise e\n    except (TimeoutError, socket.timeout) as error:\n        logging.warning(\n            \"Timed out executing Google API request; retrying with backoff. Details: %s\",\n            error,\n        )\n        results = retrieval_function()\n    return results\n\n\ndef get_credentials_from_env(email: str, oauth: bool = False, source=\"drive\") -> dict:\n    try:\n        if oauth:\n            raw_credential_string = os.environ[\"GOOGLE_OAUTH_CREDENTIALS_JSON_STR\"]\n        else:\n            raw_credential_string = os.environ[\"GOOGLE_SERVICE_ACCOUNT_JSON_STR\"]\n    except KeyError:\n        raise ValueError(\"Missing Google Drive credentials in environment variables\")\n\n    try:\n        credential_dict = json.loads(raw_credential_string)\n    except json.JSONDecodeError:\n        raise ValueError(\"Invalid JSON in Google Drive credentials\")\n\n    if oauth and source == \"drive\":\n        credential_dict = ensure_oauth_token_dict(credential_dict, DocumentSource.GOOGLE_DRIVE)\n    else:\n        credential_dict = ensure_oauth_token_dict(credential_dict, DocumentSource.GMAIL)\n\n    refried_credential_string = json.dumps(credential_dict)\n\n    DB_CREDENTIALS_DICT_TOKEN_KEY = \"google_tokens\"\n    DB_CREDENTIALS_DICT_SERVICE_ACCOUNT_KEY = \"google_service_account_key\"\n    DB_CREDENTIALS_PRIMARY_ADMIN_KEY = \"google_primary_admin\"\n    DB_CREDENTIALS_AUTHENTICATION_METHOD = \"authentication_method\"\n","sourceCodeStart":149,"sourceCodeEnd":185,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/google_util/util.py#L149-L185","documentation":"Raised by get_credentials_from_env when neither GOOGLE_OAUTH_CREDENTIALS_JSON_STR (oauth=True) nor GOOGLE_SERVICE_ACCOUNT_JSON_STR (oauth=False) is present in the process environment. The function reads credentials exclusively from os.environ, so an unset or empty variable triggers a KeyError that is converted into this ValueError. It fires before any Google API call is made, during connector credential resolution.","triggerScenarios":"Calling get_credentials_from_env(email, oauth=True) without GOOGLE_OAUTH_CREDENTIALS_JSON_STR exported, or with oauth=False without GOOGLE_SERVICE_ACCOUNT_JSON_STR. Typical when running a Google Drive or Gmail connector task in a worker process whose environment was not populated from the credential store.","commonSituations":"Deploying to a new environment (container, cron, CI) and forgetting to copy the .env entries; env vars set in the shell but lost because the worker runs under a different user, systemd unit, or docker-compose service; variable name typo (e.g. GOOGLE_SERVICE_ACCOUNT_JSON vs GOOGLE_SERVICE_ACCOUNT_JSON_STR).","solutions":["Export the correct variable: set GOOGLE_OAUTH_CREDENTIALS_JSON_STR to the JSON string of the OAuth client/token document when oauth=True, or GOOGLE_SERVICE_ACCOUNT_JSON_STR to the service-account JSON when oauth=False.","Verify the variable is visible to the same process that runs the connector: print os.environ keys (names only) or check the systemd unit / compose service environment block.","Check for name typos against the exact keys read in common/data_source/google_util/util.py:161-165.","If credentials are stored per-tenant in a DB, confirm the code path that should inject them into the environment actually ran before this call."],"exampleFix":"# before\nexport GOOGLE_SERVICE_ACCOUNT_JSON=   # empty/unset -> ValueError\npython -c \"from common.data_source.google_util.util import get_credentials_from_env; get_credentials_from_env('a@b.com')\"\n\n# after\nexport GOOGLE_SERVICE_ACCOUNT_JSON_STR=\"$(cat /path/to/service_account.json)\"\npython -c \"from common.data_source.google_util.util import get_credentials_from_env; get_credentials_from_env('a@b.com')\"","handlingStrategy":"validation","validationCode":"import os\n\nREQUIRED = {\n    True: \"GOOGLE_OAUTH_CREDENTIALS_JSON_STR\",\n    False: \"GOOGLE_SERVICE_ACCOUNT_JSON_STR\",\n}\n\ndef google_env_credentials_present(oauth: bool) -> bool:\n    return bool(os.environ.get(REQUIRED[oauth]))","typeGuard":null,"tryCatchPattern":"from common.data_source.google_util.util import get_credentials_from_env\n\ntry:\n    creds = get_credentials_from_env(email, oauth=True)\nexcept ValueError as e:\n    if 'Missing Google Drive credentials' in str(e):\n        raise RuntimeError('Environment not provisioned for Google connector') from e\n    raise","preventionTips":["Fail fast at process start: assert the required env var names exist before spawning connector tasks.","Keep env var names in one constant module and reference it everywhere instead of retyping the literal key.","Add a pre-deploy check that diffs required env keys against the target environment."],"tags":["google","credentials","environment-variables","connector"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}