infiniflow/ragflow · error · ValueError

101

101

Error message

Invalid Google credentials JSON.

What it means

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.

Source

Thrown at api/apps/restful_apis/connector_api.py:310

    return f"{prefix}:{flow_id}"


def _web_result_cache_key(flow_id: str, source_type: str | None = None) -> str:
    """Return Redis key for web OAuth result.

    Mirrors _web_state_cache_key logic for result storage.
    """
    prefix = f"{source_type}_web_flow_result"
    return f"{prefix}:{flow_id}"


def _load_credentials(payload: str | dict[str, Any]) -> dict[str, Any]:
    if isinstance(payload, dict):
        return payload
    try:
        return json.loads(payload)
    except json.JSONDecodeError as exc:  # pragma: no cover - defensive
        raise ValueError("Invalid Google credentials JSON.") from exc


def _get_web_client_config(credentials: dict[str, Any]) -> dict[str, Any]:
    web_section = credentials.get("web")
    if not isinstance(web_section, dict):
        raise ValueError("Google OAuth JSON must include a 'web' client configuration to use browser-based authorization.")
    return {"web": web_section}


def _exchange_google_web_oauth_code(
    client_config: dict[str, Any],
    scopes: list[str],
    redirect_uri: str,
    code: str,
    code_verifier: str | None,
) -> Flow:
    flow = Flow.from_client_config(client_config, scopes=scopes)
    flow.redirect_uri = redirect_uri

View on GitHub (pinned to 554fb1133a)

Solutions

  1. Re-download the OAuth client JSON from Google Cloud Console and paste it verbatim.
  2. Validate the string with any JSON linter before submitting; fix syntax errors (trailing commas, unescaped newlines).
  3. If building the request programmatically, pass the credentials as a dict (the function accepts dicts directly) or use json.dumps().

Example fix

# before - broken string
credentials = "{client_id: 'abc',}"  # not valid JSON
# after
credentials = {"installed": {"client_id": "abc", "client_secret": "..."}}
Defensive patterns

Strategy: validation

Validate before calling

import json

def validate_credentials_payload(payload):
    if isinstance(payload, dict):
        return payload
    try:
        return json.loads(payload)
    except (TypeError, json.JSONDecodeError):
        raise ValueError("credentials string is not valid JSON - re-download from Google Cloud Console")

Try / catch

try:
    connector = client.create_connector(source_type="google", credentials=raw)
except ValueError as e:
    if "Invalid Google credentials JSON" in str(e):
        raise ValueError("Google credentials must be the verbatim client-secret JSON") from e
    raise

Prevention

When it happens

Trigger: 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.

Common situations: 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.

Related errors


AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15). Data as JSON: /api/errors/12fb95c791393b17. Report an issue: GitHub.