infiniflow/ragflow · error · ConnectorMissingCredentialError
BigQuery: service_account_json must be a JSON string or obje
Error message
BigQuery: service_account_json must be a JSON string or object
What it means
Type-validation branch in load_credentials: service_account_json exists but is neither a str nor a dict (e.g. a list, int, or nested structure). The connector accepts exactly two shapes — JSON string or mapping — and rejects anything else as a credential error.
Source
Thrown at common/data_source/bigquery_connector.py:163
"""Load BigQuery service-account credentials.
Accepts ``service_account_json`` as either a dict or a JSON string.
"""
logging.debug("Loading credentials for BigQuery project: %s", self.project_id)
raw = (credentials or {}).get("service_account_json")
if not raw:
raise ConnectorMissingCredentialError("BigQuery: missing service_account_json")
if isinstance(raw, str):
try:
service_account_info = json.loads(raw)
except json.JSONDecodeError as exc:
raise ConnectorMissingCredentialError(f"BigQuery: service_account_json is not valid JSON: {exc}")
elif isinstance(raw, dict):
service_account_info = raw
else:
raise ConnectorMissingCredentialError("BigQuery: service_account_json must be a JSON string or object")
self._credentials = {"service_account_info": service_account_info}
return None
def _get_client(self):
"""Create and cache a BigQuery client from the loaded service account."""
if self._client is not None:
return self._client
if bigquery is None or service_account is None:
raise ConnectorValidationError("BigQuery client not installed. Please install google-cloud-bigquery.")
service_account_info = self._credentials.get("service_account_info")
if not service_account_info:
raise ConnectorMissingCredentialError("BigQuery credentials not loaded.")
try:
creds = service_account.Credentials.from_service_account_info(service_account_info)View on GitHub (pinned to 554fb1133a)
Solutions
- Pass the parsed dict, the JSON string, or decode bytes first: raw.decode('utf-8')
- Remove accidental list wrapping: use sa_json, not [sa_json]
- Add a pre-flight isinstance check in the config loader so the wrong shape is caught at config time
Example fix
# before
creds = {"service_account_json": [sa_dict]}
# or
creds = {"service_account_json": key_file_bytes}
# after
creds = {"service_account_json": sa_dict}
# or
creds = {"service_account_json": key_file_bytes.decode("utf-8")} Defensive patterns
Strategy: type-guard
Validate before calling
def normalize_sa_input(raw):
if isinstance(raw, bytes):
raw = raw.decode("utf-8")
if isinstance(raw, list) and len(raw) == 1:
raw = raw[0] # unwrap accidental list
if not isinstance(raw, (str, dict)):
raise TypeError(f"service_account_json must be str|dict, got {type(raw).__name__}")
return raw Type guard
def is_sa_json_shape(raw) -> bool:
return isinstance(raw, (str, dict)) Try / catch
try:
connector.load_credentials(creds)
except ConnectorMissingCredentialError as e:
if "must be a JSON string or object" in str(e):
creds["service_account_json"] = normalize_sa_input(creds["service_account_json"])
connector.load_credentials(creds)
else:
raise Prevention
- Decode bytes and unwrap single-element lists at the config boundary
- Type credential fields in your config layer (pydantic/mypy) so wrong shapes fail at load time
- Add unit tests asserting both accepted shapes (str and dict) and rejection of list/bytes
When it happens
Trigger: Passing service_account_json as a list (e.g. [sa_dict] accidentally wrapped), an int/bool from a misconfigured form, or bytes (an encoded JSON key file read as b'...') — bytes are not decoded, so they fail this branch.
Common situations: Glue code that wraps the value in a list 'just in case', reading the key file in binary mode and passing bytes, or a config schema that auto-parses JSON into a list structure.
Related errors
- BigQuery: missing service_account_json
- BigQuery: service_account_json is not valid JSON: {exc}
- Failed to build BigQuery credentials: {exc}
- Failed to create BigQuery client: {exc}
- main() returned a non-JSON-serializable value.
AI-assisted analysis of infiniflow/ragflow@554fb1133a (2026-08-15).
Data as JSON: /api/errors/1fd482b35a934257.
Report an issue: GitHub.