HumanSignal/label-studio · error · ValueError
Google Application Credentials must be valid JSON string. {e
Error message
Google Application Credentials must be valid JSON string. {e} What it means
get_client caches and builds a google-cloud-storage Client. When google_application_credentials is a string it must be the parsed JSON of a service account; a JSONDecodeError is re-raised as a ValueError telling the user the credentials must be a valid JSON string. Raised for any GCS operation: get_bucket, validate_connection, generate_http_url, get_blob_metadata, validate_pattern.
Source
Thrown at label_studio/io_storages/gcs/utils.py:71
cls, google_project_id: str = None, google_application_credentials: Union[str, dict] = None
) -> gcs.Client:
"""
:param google_project_id:
:param google_application_credentials:
:return:
"""
google_project_id = google_project_id or GCS.DEFAULT_GOOGLE_PROJECT_ID
cache_key = google_application_credentials
if cache_key not in GCS._client_cache:
# use credentials from LS Cloud Storage settings
if google_application_credentials:
if isinstance(google_application_credentials, str):
try:
google_application_credentials = json.loads(google_application_credentials)
except JSONDecodeError as e:
# change JSON error to human-readable format
raise ValueError(f'Google Application Credentials must be valid JSON string. {e}')
credentials = service_account.Credentials.from_service_account_info(google_application_credentials)
GCS._client_cache[cache_key] = gcs.Client(project=google_project_id, credentials=credentials)
# use Google Application Default Credentials (ADC)
else:
GCS._client_cache[cache_key] = gcs.Client(project=google_project_id)
return GCS._client_cache[cache_key]
@classmethod
def validate_connection(
cls,
bucket_name: str,
google_project_id: str = None,
google_application_credentials: Union[str, dict] = None,
prefix: str = None,
use_glob_syntax: bool = False,
):View on GitHub (pinned to 0b49e9b539)
Solutions
- Paste/read the actual JSON contents: with open('key.json') as f: creds = f.read(), then pass that string — not the path
- If the secret is base64, decode it first: base64 -d key.b64 > key.json and use its contents
- Validate the JSON before saving: python -m json.tool key.json; fix truncation/escaping (private_key newlines must survive as \n inside the JSON)
- Alternatively unset the credentials field and rely on Application Default Credentials (ADC) on a GCE/GKE instance with a proper service account
Example fix
// before GOOGLE_APPLICATION_CREDENTIALS=/secrets/key.json // path -> JSONDecodeError // after export GOOGLE_APPLICATION_CREDENTIALS=$(cat /secrets/key.json) # raw JSON string # or leave unset and use ADC
Defensive patterns
Strategy: validation
Validate before calling
import json
def credentials_field_ok(creds):
if not creds:
return True, 'using ADC'
try:
json.loads(creds)
return True, None
except json.JSONDecodeError as e:
return False, str(e) Type guard
def is_service_account_json(s):
import json
try:
d = json.loads(s) if isinstance(s, str) else s
return isinstance(d, dict) and d.get('type') == 'service_account' and 'private_key' in d
except (json.JSONDecodeError, TypeError):
return False Try / catch
try:
client = GCS.get_client(cache_key, google_project_id, google_application_credentials)
except ValueError as e:
if 'valid JSON string' in str(e):
logger.error('Read the file contents: creds = open(path).read() — not the path itself') Prevention
- Pass the file contents (open(path).read()), never a path string
- Validate with json.loads before setting the env var/UI field
- Decode base64 CI secrets before use
- Prefer ADC on GCE/GKE instead of embedding key JSON
When it happens
Trigger: Setting GOOGLE_APPLICATION_CREDENTIALS (or the storage field) to a file path instead of file contents, to a base64 blob, or to a truncated/corrupted JSON string; environment variable interpolation mangling newlines in the private key.
Common situations: Users copying the credentials file path into the UI field expecting Label Studio to read it; Docker/K8s secret mounted as a path then referenced directly; CI systems that base64-encode secrets; quotes/escaping lost when pasting into the settings form.
Related errors
- Azure account name and key must be set using environment var
- extract_message(exc)
- No blobs found in {bucket_name}/{prefix} or prefix doesn't e
- When "FEATURE_FLAGS_FROM_FILE" is set, you have to specify a
- LABEL_STUDIO_HOST must be a subpath if DOMAIN_FROM_REQUEST i
AI-assisted analysis of HumanSignal/label-studio@0b49e9b539 (2026-08-29).
Data as JSON: /api/errors/61ef05a7daa03c78.
Report an issue: GitHub.