xtekky/gpt4free · error · RuntimeError
Failed to save: {auth_result.get_dict()}\n{type(e).__name__}
Error message
Failed to save: {auth_result.get_dict()}\n{type(e).__name__}: {e} What it means
RuntimeError raised inside AsyncAuthedProvider.write_cache_file when json.dump of the AuthResult fails with TypeError while persisting the auth cache to auth_<Provider>.json. It chains the original TypeError and includes auth_result.get_dict() in the message, so the failing object is visible. It indicates the auth result contains an object the toJSON fallback (str()) could not serialize — i.e. get_dict() itself returned or threw on non-serializable content.
Source
Thrown at g4f/providers/base_provider.py:453
if "api_key" not in kwargs:
raise MissingAuthError(f"API key is required for {cls.__name__}")
return AuthResult()
@classmethod
def write_cache_file(cls, cache_file: Path, auth_result: AuthResult = None):
if auth_result is not None:
cache_file.parent.mkdir(parents=True, exist_ok=True)
try:
def toJSON(obj):
if hasattr(obj, "get_dict"):
return obj.get_dict()
return str(obj)
with cache_file.open("w") as cache_file:
json.dump(auth_result, cache_file, default=toJSON)
except TypeError as e:
raise RuntimeError(
f"Failed to save: {auth_result.get_dict()}\n{type(e).__name__}: {e}"
)
# elif cache_file.exists():
# cache_file.unlink()
@classmethod
def get_auth_result(cls) -> AuthResult:
"""
Retrieves the authentication result from cache.
"""
cache_file = cls.get_cache_file()
if cache_file.exists():
try:
with cache_file.open("r") as f:
return AuthResult(**json.load(f))
except json.JSONDecodeError:
cache_file.unlink()
raise MissingAuthError(f"Invalid auth file: {cache_file}")View on GitHub (pinned to 973504e177)
Solutions
- Read the embedded get_dict() dump in the message to identify which field is non-serializable.
- Fix the provider's AuthResult so get_dict() returns plain JSON types (str/int/float/bool/list/dict) — convert bytes/datetimes in get_dict.
- As a caller, delete the cache file and re-authenticate after fixing the serialization, so a partial file is not reused.
- If you do not control the subclass, catch RuntimeError around the first authenticated call and report it as a provider bug.
Example fix
// before
class MyResult(AuthResult):
def get_dict(self) -> dict:
return {'token': self.session, 'expiry': self.expires} # session is a requests.Session
// after
class MyResult(AuthResult):
def get_dict(self) -> dict:
return {'token': self.session.headers['Authorization'], 'expiry': str(self.expires)} Defensive patterns
Strategy: try-catch
Validate before calling
import json d = auth_result.get_dict() json.dumps(d) # raises TypeError here (before caching) if any field is non-serializable
Try / catch
try:
await provider.create_async_generator(model, messages, api_key=key)
except RuntimeError as e:
if 'Failed to save' in str(e):
logging.error('auth cache serialization bug in provider %s: %s', provider.__name__, e)
# the request itself may have succeeded; treat as non-fatal but report upstream
else:
raise Prevention
- Subclass authors: make get_dict() return only JSON primitives.
- Smoke-test get_dict() with json.dumps() in unit tests for custom AuthResults.
- Delete the possibly-partial cache file after this error before retrying.
When it happens
Trigger: A provider's on_auth_async returns an AuthResult holding custom objects whose get_dict() returns nested non-JSON-serializable values (bytes, datetime, requests objects); the write path then hits TypeError from json.dump and re-raises as RuntimeError.
Common situations: Custom AsyncAuthedProvider subclasses added by downstream projects; provider upgrades that add new fields (e.g. raw HTTP sessions or cookie jars) to AuthResult; disk state is fine — the failure is purely serialization.
Related errors
- Invalid auth file: {cache_file}
- result
- Failed to parse message: {chunk.decode(errors='replace')}
- Failed to read response: {chunk.decode(errors='replace')}
- Failed to parse image URL: {chunk.decode(errors='replace')}
AI-assisted analysis of xtekky/gpt4free@973504e177 (2026-08-14).
Data as JSON: /api/errors/0df2b78990df9495.
Report an issue: GitHub.