- env= -> environment= across all docs (Pydantic silently ignores env=) - Remove __version__ check (doesn't exist in module) - Fix APIClient(debug=True) missing required client_id/secret - Fix post.listremoved usage (takes no postId, just lists removed posts) - Fix JS true/false -> Python True/False in code blocks - Fix parameter names: branchName->branch_slug, username->user_slug, postId->post_id - Add missing lastEvaluatedKey param docs for list jobs - Note post.listpublic as unauthenticated endpoint - Fix pagination examples (LastEvaluatedKey, not ExclusiveStartKey dict) - Remove non-existent headers param from make_request example - Fix branch.listbyname example (takes no name arg) - Add 4 missing wrapper docs: follow, react, trust, votecast - Fix broken internal links (case-sensitive filenames) - Fix <environment>_handle_token template artifact - Add CODE_BUGS.md documenting 4 code bugs found during audit
15 KiB
Troubleshooting Guide
Common issues and solutions when using the TrustCafé API wrapper.
Table of Contents
- Authentication Issues
- Connection Issues
- Token Management Issues
- API Call Issues
- Environment Issues
- Data Handling Issues
- Performance Issues
- Debugging Strategies
Authentication Issues
Issue: "Invalid client credentials"
Symptoms:
ValueError: Client credentials invalid
Causes:
- Incorrect client_id or client_secret
- Using alpha credentials on production environment (or vice versa)
- Credentials haven't been saved yet from the TrustCafé admin panel
Solutions:
-
Verify credentials from the admin panel
-
Ensure environment matches credentials:
# Check your credentials are for the right environment print(f"Environment: {env}") # Should match where credentials were created -
Generate new credentials if needed:
- Visit: https://www.trustcafe.io/en/myaccount/apiaccess
- Click "Create new client credentials key pair"
- Save the new credentials
-
Verify credentials aren't expired (trustcafe-side expiration)
Issue: "Token expired"
Symptoms:
Exception: Token has expired
Causes:
- Access token duration has expired (~3 months from creation)
- Time mismatch between systems
Solutions:
-
Automatically refresh token:
# Check token validity and refresh if needed if not API.is_token_valid(): API.handle_token() -
Pre-load tokens before long operations:
# Ensure token is fresh before making many requests API.handle_token() # Now all API calls will succeed -
Provide longer expiration time for testing:
# Manual token with long expiration API.set_token({ "access_token": "your-token", "access_token_timeout": 9999999999 # Far future date })
Issue: "Permission denied" when making requests
Symptoms:
ForbiddenError: Insufficient permissions for this API endpoint
Causes:
- Client credentials lack required scopes
- Not authenticated (no access token)
Solutions:
- Verify scopes on the admin panel
- Ensure authentication is enabled in all requests:
# Make sure to authenticate response = API.make_request( "GET", "content", "some/path", authenticate=True # Ensure this is True ) # For guest requests (if allowed) response = API.make_request( "GET", "content", "some/path", authenticate=False )
Connection Issues
Issue: "No internet connection" or "Connection refused"
Symptoms:
ConnectionError: An error occurred while making the request
Causes:
- Network connectivity issues
- Firewall blocking requests
- API service unavailable
Solutions:
-
Check network connectivity:
# Test connectivity to alpha/production endpoints ping alpha.wts2.net ping trustcafe.io -
Verify firewall rules allow HTTPS requests
-
Try alternative network (mobile hotspot vs. Wi-Fi)
-
Check if TrustCafé services are up:
- Production: https://trustcafe.io
- Alpha: https://alpha.wts2.net
-
Add retry logic:
import time def retry_request(request_func, max_retries=3): for attempt in range(max_retries): try: return request_func() except ConnectionError as e: if attempt < max_retries - 1: time.sleep(1) else: raise
Issue: "DNS resolution failed"
Symptoms:
requests.exceptions.ConnectionError: DNS resolution failed
Causes:
- DNS server issues
- VPN interfering with DNS
- Incorrect hostname
Solutions:
-
Check DNS:
nslookup alpha.wts2.net nslookup trustcafe.io -
Try changing DNS server:
# Use Google DNS (8.8.8.8, 8.8.4.4) # Or Cloudflare (1.1.1.1, 1.0.0.1) -
Disable VPN temporarily
-
Check configuration for correct hostnames (alpha.wts2.net vs trustcafe.io)
Token Management Issues
Issue: "Token file not found"
Symptoms:
FileNotFoundError: Token data file 'token_data_alpha.json' not found
Causes:
- First-time run
- Token directory not created
- Wrong path specified
Solutions:
-
API
handle_tokenautomatically creates file on first use -
Ensure working directory is writable
-
Specify custom token file path:
API.handle_token(token_data_path="my/custom/path/token_data.json") -
Manually create token file:
token_data = API.sign_in() with open("token_data_alpha.json", "w") as f: json.dump(token_data, f)
Issue: "Permission denied: cannot write token file"
Symptoms:
PermissionError: [Errno 13] Permission denied: 'token_data_alpha.json'
Causes:
- Working directory not writable
- File locked by another process
- Insufficient permissions
Solutions:
-
Ensure writable directory:
import os # Use a writable directory writable_dir = os.path.expanduser("~") # Home directory API.handle_token(token_data_path=f"{writable_dir}/tokens/token_data.json") -
Check file permissions:
ls -la token_data_alpha.json chmod 644 token_data_alpha.json -
Try with a custom directory:
import tempfile # Use temp directory with tempfile.TemporaryDirectory() as tmpdir: API.handle_token(token_data_path=f"{tmpdir}/token_data.json")
Issue: "Token file corrupted"
Symptoms:
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
Causes:
- File corruption during write
- File truncated by other process
Solutions:
-
Delete corrupted token file:
rm token_data_alpha.json -
Let wrapper recreate it
-
Check for concurrent token writes:
from threading import Lock token_lock = Lock() def safe_handle_token(): with token_lock: API.handle_token()
API Call Issues
Issue: "400 Bad Request" or "Invalid parameter"
Symptoms:
ValueError: Invalid parameter or data format
400 Bad Request
Causes:
- Missing required parameters
- Incorrect parameter format
- Parameter validation failure
Solutions:
-
Check parameter requirements in API Reference:
- See API Reference for each job
-
Verify parameter types:
# Use correct types API.run_job('post.create', { "postText": "text string", # Should be string "blurLabel": None, # None is okay # Wrong: "blurLabel": "" (empty string) }) -
Verify required parameters:
# Example for post.create required_fields = ['postText', 'parent'] if 'parent' not in data: raise ValueError("Required field 'parent' is missing") -
Use debug mode to see request:
API = APIClient(client_id="your-id", client_secret="your-secret", debug=True) # Now you'll see the exact data being sent API.run_job('post.create', data)
Issue: "404 Not Found"
Symptoms:
FileNotFoundError: Endpoint not found
404 Not Found
Causes:
- Wrong endpoint or path
- Resource doesn't exist
- Branch/post not found
Solutions:
-
Verify the path is correct
-
Check if resource exists:
# Verify branch exists branch = API.run_job('branch.get', "branch-name") if not branch: print("Branch does not exist") # Verify post exists post = API.run_job('post.get', "post-id") if not post: print("Post does not exist") -
Check for spelling mistakes in paths
-
Use debug mode to see exact path being sent:
API = APIClient(client_id="your-id", client_secret="your-secret", debug=True) API.run_job('post.create', data) # See exact request path
Issue: "500 Internal Server Error"
Symptoms:
ConnectionError: An error occurred
500 Internal Server Error
Causes:
- TrustCafé server error
- Database issues on server side
- Unhandled edge case
Solutions:
- Wait a moment and retry
- Check TrustCafé status
- Try at a different time
- Consider this transient error:
import time def retry_server_error(func, max_retries=3): for attempt in range(max_retries): try: return func() except ConnectionError as e: if str(e).find("500") != -1: if attempt < max_retries - 1: time.sleep(2 ** attempt) # Exponential backoff else: raise
Issue: "Rate limit exceeded"
Symptoms:
429 Too Many Requests
Causes:
- Too many API calls too quickly
- Gratuitous API usage
Solutions:
-
Implement rate limiting (see main README for example)
-
Space out your API calls:
import time def spaced_request(request_func, delay=1): result = request_func() if hasattr(request_func, 'call_count'): request_func.call_count += 1 if request_func.call_count > 30: time.sleep(2) return result -
Use pagination for large result sets
-
Consider caching results when possible
Environment Issues
Issue: "Environment 'invalid' is not valid"
Symptoms:
ValueError: Environment 'staging' is not valid. Must be one of: ['alpha', 'production']
Causes:
- Typo in environment name
- Passing only environment once
- Environment changed incorrectly
Solutions:
-
Use correct environment names:
- "alpha" (development/staging)
- "production" (live)
-
Avoid modifying environment mid-session after API init
-
Reinitialize if you need to switch:
# Create new API client for new environment API_prod = APIClient( client_id="prod-id", client_secret="prod-secret", environment="production" ) # Old API still has old environment print(API.environment) # "alpha"
Issue: "Endpoint 'invalid' is not defined"
Symptoms:
ValueError: Endpoint 'noservices' is not defined in the API client.
Causes:
- Typo in endpoint name
- Custom endpoint not configured
- Server-side endpoint changed
Solutions:
- Check available endpoints in APIClient code
- Use correct endpoints: "content", "auth", "audrey", etc.
- Review documentation for correct API structure
Data Handling Issues
Issue: "JSON decode error" or "Response is not valid JSON"
Symptoms:
ValueError: Response is not valid JSON: Expecting value: line 1 column 1 (char 0)
Causes:
- Server returning non-JSON response
- Network error causing incomplete response
- Empty response
Solutions:
-
Add error handling:
try: response = API.make_request("GET", "content", "path") response_json = response.json() except json.JSONDecodeError as e: print(f"Failed to parse JSON: {e}") print(f"Response was: {response}") -
Check if server is responding correctly
-
Verify network connectivity
-
Check for errors in response:
if 'error' in response: raise Exception(f"API Error: {response['error']}")
Issue: Empty response or missing data
Symptoms:
expected to find Items in response, but didn't
Causes:
- Query returns no results
- Pagination not handled
- Response structure misunderstanding
Solutions:
-
Check for empty results:
response = API.make_request("GET", "content", "some/path") if 'Items' not in response or not response.get('Items'): print("No results found") -
Check pagination status:
if 'LastEvaluatedKey' in response: print("More results available, need pagination") -
Verify response structure understanding
Performance Issues
Issue: "Timeout" errors
Symptoms:
requests.exceptions.Timeout: Request timed out
Causes:
- Network slowness
- Large result sets
- Slow server response
Solutions:
-
Increase timeout:
# Unfortunately, current implementation doesn't expose timeout # This would need updating in apiclient.py # If you control code, you can modify the make_request method # to accept a timeout parameter -
Reduce request complexity
-
Implement pagination for large datasets
-
Use async if available
Issue: Slow token refresh
Symptoms:
- Initial request slow
- Token refresh takes too long
Causes:
- Network latency to auth endpoint
- Server-side delays
Solutions:
-
Pre-load token:
# Get token before doing anything time-sensitive API.handle_token() # All subsequent calls will use cached token -
Use manual token for frequent operations:
API.set_token({ "access_token": token, "access_token_timeout": 9999999999 })
Debugging Strategies
Enable Debug Mode
API = APIClient(
client_id="your-id",
client_secret="your-secret",
environment="alpha",
debug=True # Enables verbose logging
)
This will print:
- Request method
- Full URL
- Headers
- Request payload
Add Logging
import logging
logging.basicConfig(level=logging.DEBUG)
logger = logging.getLogger(__name__)
try:
result = API.run_job('post.create', data)
logger.debug(f"Success: {result}")
except Exception as e:
logger.error(f"Failed: {e}", exc_info=True)
Verify Request Flow
def trace_request(func, *args, **kwargs):
"""Trace each request"""
import inspect
# Get function name
func_name = inspect.getmember(BuiltinFunctionType, func).__name__
print(f"Calling: {func_name}")
print(f"Args: {args}")
print(f"Kwargs: {kwargs}")
result = func(*args, **kwargs)
print(f"Result: {result}")
return result
Network Inspection
import requests
# Direct inspection of requests
import logging
requests_log = logging.getLogger("urllib3")
requests_log.setLevel(logging.DEBUG)
requests_log.propagate = True
Getting Help
If you've tried all of the above and still have issues:
-
Check the Code: Review the latest version on GitLab
-
Check TrustCafé Status: Verify services are up
-
Review Contributions: Check for known issues
- Open an issue on GitLab
- Check if a fix is already in progress
-
Contact Support: For resolved but unreleased issues
- WikiTribune team
- Build Product Slack/Discord
Quick Reference
Common error codes:
- 400 Bad Request: Invalid parameters (check API Reference)
- 401 Unauthorized: Invalid/missing token (call
handle_token()) - 403 Forbidden: Insufficient permissions (check scopes)
- 404 Not Found: Wrong path or resource doesn't exist
- 429 Too Many Requests: Rate limit exceeded (apply rate limiting)
- 500 Internal Server Error: Service error (wait and retry)
- Timeout: Network issues (check connectivity)
Remember: Most issues are easily solved with proper error handling, verification of credentials, and rate limiting.