{"record":{"id":"12fb95c791393b17","repo":"infiniflow/ragflow","slug":"101","errorCode":"101","errorMessage":"Invalid Google credentials JSON.","messagePattern":"Invalid Google credentials JSON\\.","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"api/apps/restful_apis/connector_api.py","lineNumber":310,"sourceCode":"    return f\"{prefix}:{flow_id}\"\n\n\ndef _web_result_cache_key(flow_id: str, source_type: str | None = None) -> str:\n    \"\"\"Return Redis key for web OAuth result.\n\n    Mirrors _web_state_cache_key logic for result storage.\n    \"\"\"\n    prefix = f\"{source_type}_web_flow_result\"\n    return f\"{prefix}:{flow_id}\"\n\n\ndef _load_credentials(payload: str | dict[str, Any]) -> dict[str, Any]:\n    if isinstance(payload, dict):\n        return payload\n    try:\n        return json.loads(payload)\n    except json.JSONDecodeError as exc:  # pragma: no cover - defensive\n        raise ValueError(\"Invalid Google credentials JSON.\") from exc\n\n\ndef _get_web_client_config(credentials: dict[str, Any]) -> dict[str, Any]:\n    web_section = credentials.get(\"web\")\n    if not isinstance(web_section, dict):\n        raise ValueError(\"Google OAuth JSON must include a 'web' client configuration to use browser-based authorization.\")\n    return {\"web\": web_section}\n\n\ndef _exchange_google_web_oauth_code(\n    client_config: dict[str, Any],\n    scopes: list[str],\n    redirect_uri: str,\n    code: str,\n    code_verifier: str | None,\n) -> Flow:\n    flow = Flow.from_client_config(client_config, scopes=scopes)\n    flow.redirect_uri = redirect_uri","sourceCodeStart":292,"sourceCodeEnd":328,"githubUrl":"https://github.com/infiniflow/ragflow/blob/554fb1133ac3861732235ad9c377eb5e0a770665/api/apps/restful_apis/connector_api.py#L292-L328","documentation":"Raised by _load_credentials in the connector API when Google OAuth credentials are supplied as a string that fails json.loads(). The connector expects either a dict or a JSON-serialized Google credentials object; malformed JSON (trailing commas, smart quotes, truncation) triggers this ValueError.","triggerScenarios":"Creating/updating a Google-type connector with credentials pasted as a string that is not valid JSON — e.g. copy-paste truncated the file, quotes were converted to typographic quotes, or the value was double-escaped when stored/retrieved.","commonSituations":"Pasting the downloaded Google client_secret JSON into a form that mangles it, storing the JSON in an env var with shell escaping issues, or wrapping it in extra quotes so it arrives as a quoted string.","solutions":["Re-download the OAuth client JSON from Google Cloud Console and paste it verbatim.","Validate the string with any JSON linter before submitting; fix syntax errors (trailing commas, unescaped newlines).","If building the request programmatically, pass the credentials as a dict (the function accepts dicts directly) or use json.dumps()."],"exampleFix":"# before - broken string\ncredentials = \"{client_id: 'abc',}\"  # not valid JSON\n# after\ncredentials = {\"installed\": {\"client_id\": \"abc\", \"client_secret\": \"...\"}}","handlingStrategy":"validation","validationCode":"import json\n\ndef validate_credentials_payload(payload):\n    if isinstance(payload, dict):\n        return payload\n    try:\n        return json.loads(payload)\n    except (TypeError, json.JSONDecodeError):\n        raise ValueError(\"credentials string is not valid JSON - re-download from Google Cloud Console\")","typeGuard":null,"tryCatchPattern":"try:\n    connector = client.create_connector(source_type=\"google\", credentials=raw)\nexcept ValueError as e:\n    if \"Invalid Google credentials JSON\" in str(e):\n        raise ValueError(\"Google credentials must be the verbatim client-secret JSON\") from e\n    raise","preventionTips":["Validate credentials JSON in CI with json.loads before deploying connector configs.","Store the file, not a hand-edited string; read and pass it untouched.","Beware shell/env escaping that adds quotes or strips newlines."],"tags":["connector-api","oauth","google","json","configuration"],"backgroundTag":null,"analyzedSha":"554fb1133ac3861732235ad9c377eb5e0a770665","analyzedAt":"2026-08-15T09:20:16.380Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}