apache/beam · error · TypeError
Secret 'spec' must be a string, got
Error message
Secret 'spec' must be a string, got {type(spec).__name__} What it means
Secret.from_json builds a Secret from a JSON spec string plus a secret manager name. Because the spec must be parseable JSON text, a non-str spec (dict, bytes, None) raises TypeError naming the actual type received.
Solutions
- Serialize the spec: Secret.from_json(json.dumps(param_map), secret_manager)
- Ensure the value is not None before calling (check upstream parsing)
- If you have a dict, use parse_secret_option or json.dumps first
Example fix
// before
Secret.from_json({'name': 'my-secret'}, 'GoogleCloudSecretManager')
// after
import json
Secret.from_json(json.dumps({'name': 'my-secret'}), 'GoogleCloudSecretManager') Defensive patterns
Strategy: type-guard
Validate before calling
if not isinstance(spec, str):
raise TypeError(f'spec must be a JSON string, got {type(spec).__name__}') Type guard
def is_str_spec(spec):
return isinstance(spec, str) Try / catch
try:
secret = Secret.from_json(spec, secret_manager)
except TypeError as e:
logging.error('bad spec type: %s', e)
secret = Secret.from_json(json.dumps(spec), secret_manager) # if spec is a dict Prevention
- Always json.dumps dicts before from_json
- Check for None specs when plumbing parsed config
- Keep the spec as a string end-to-end once parsed
When it happens
Trigger: Calling from_json with a dict (e.g. {'name': ...}) instead of json.dumps of it, or with None/bytes when wiring parameters through parse_secret_option.
Common situations: Passing an already-parsed dict from YAML config; API change where callers used to accept dicts; forgetting json.dumps when constructing the spec.
Understand the failure class
Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.
Related errors
- Only strings allowd as map keys when converting from JSON…
- Only strings allowd as map keys when converting to JSON…
- Unable to get value from field
- Unsupported secret manager
- A sink must inherit iobase.Sink, iobase.NativeSink, or be a…
AI-assisted analysis of apache/beam@12126d8942 (2026-09-13).
Data as JSON: /api/errors/d429ec6fba77b0ab.
Report an issue: GitHub.
Appendix: source
Thrown at sdks/python/apache_beam/utils/secret.py:128
f'Invalid secret type {secret_type}, currently only '
'GcpSecret and GcpHsmGeneratedSecret are supported')
return cls.from_json(json.dumps(param_map), secret_manager)
@classmethod
def from_json(
cls, spec: str, secret_manager: Optional[str] = None) -> 'Secret':
"""Return a Secret instance based on secret_manager provider and secret specification.
Args:
spec: Secret string (raw secret or JSON specification string).
secret_manager: Secret manager string (e.g. 'GoogleCloudSecretManager').
Returns:
An instance of Secret.
"""
if not isinstance(spec, str):
raise TypeError(
f"Secret 'spec' must be a string, got {type(spec).__name__}")
secret_manager_name = (
secret_manager.strip()
if secret_manager and secret_manager.strip() else None)
spec_dict = None
try:
spec_dict = json.loads(spec)
if not isinstance(spec_dict, dict):
spec_dict = None
except Exception:
try:
import ast
spec_dict = ast.literal_eval(spec)
if not isinstance(spec_dict, dict):
spec_dict = None
except Exception:View on GitHub (pinned to 12126d8942)