{"record":{"id":"3abc11f35605d8a0","repo":"infiniflow/ragflow","slug":"invalid-json-in-google-drive-credentials","errorCode":null,"errorMessage":"Invalid JSON in Google Drive credentials","messagePattern":"Invalid JSON in Google Drive credentials","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"common/data_source/google_util/util.py","lineNumber":172,"sourceCode":"            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\n    cred_key = DB_CREDENTIALS_DICT_TOKEN_KEY if oauth else DB_CREDENTIALS_DICT_SERVICE_ACCOUNT_KEY\n\n    return {\n        cred_key: refried_credential_string,\n        DB_CREDENTIALS_PRIMARY_ADMIN_KEY: email,","sourceCodeStart":154,"sourceCodeEnd":190,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/common/data_source/google_util/util.py#L154-L190","documentation":"Raised by get_credentials_from_env after the credential string was found in the environment but json.loads() raised JSONDecodeError. The value must be a complete, valid JSON document (an OAuth token dict or a service-account key file serialized as a string). Common corruption sources are shell quoting damage, trailing junk, or pasting only part of the JSON.","triggerScenarios":"GOOGLE_SERVICE_ACCOUNT_JSON_STR contains single-quoted pseudo-JSON, a truncated paste, or literal backslash-n sequences from a bad echo. Any call to get_credentials_from_env will hit json.loads and raise this ValueError.","commonSituations":"Exporting JSON with unescaped quotes in docker-compose YAML; copying the JSON from a web console and losing the closing brace; double-encoding (storing json.dumps(json.dumps(x))); Windows line endings or a BOM prepended by an editor.","solutions":["Validate the value locally: python -c \"import json,os; json.loads(os.environ['GOOGLE_SERVICE_ACCOUNT_JSON_STR'])\" and re-export a clean copy until it parses.","Load from the file instead of inline quoting: export GOOGLE_SERVICE_ACCOUNT_JSON_STR=\"$(cat service_account.json)\".","In compose files, use the YAML pipe form or an env_file to avoid quote mangling.","Confirm the string is the JSON document itself, not a base64 blob or a path to the file."],"exampleFix":"# before (shell-mangled JSON)\nexport GOOGLE_SERVICE_ACCOUNT_JSON_STR=\"{'type': 'service_account', ...}\"  # single quotes -> JSONDecodeError\n\n# after\nexport GOOGLE_SERVICE_ACCOUNT_JSON_STR=\"$(cat /secure/service_account.json)\"","handlingStrategy":"validation","validationCode":"import json, os\n\ndef google_env_credentials_valid(oauth: bool) -> bool:\n    key = \"GOOGLE_OAUTH_CREDENTIALS_JSON_STR\" if oauth else \"GOOGLE_SERVICE_ACCOUNT_JSON_STR\"\n    raw = os.environ.get(key)\n    if not raw:\n        return False\n    try:\n        return isinstance(json.loads(raw), dict)\n    except json.JSONDecodeError:\n        return False","typeGuard":"def is_credential_json(raw) -> bool:\n    if not isinstance(raw, str) or not raw.strip():\n        return False\n    try:\n        return isinstance(json.loads(raw), dict)\n    except json.JSONDecodeError:\n        return False","tryCatchPattern":"try:\n    creds = get_credentials_from_env(email, oauth=True)\nexcept ValueError as e:\n    if 'Invalid JSON' in str(e):\n        log.error('Credential env var is corrupt JSON; re-provision from the source JSON file')\n        raise\n    raise","preventionTips":["Load credential env vars from files with $(cat file.json) rather than pasting JSON inline.","Validate JSON parseability in CI for every secret file before deployment.","Never hand-edit serialized JSON in env files; regenerate from the source document."],"tags":["google","credentials","json","connector"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}