- Fix update_post() wrapper documentation (post_id -> post_text/post_path/post_key) - Fix create_comment() wrapper documentation (added post_slug, post_key parameters) - Add missing wrapper docs for follow(), trust(), votecast(), react() - Fix reaction job parameters (parent_id -> parent_sk, corrected payload structure) - Fix trust job parameters (updated to match actual payload structure) - Fix vote job parameters (voteType -> vote, added parent structure) - Clearly mark Block and Mute jobs as NOT IMPLEMENTED - Fix GitLab URLs to Forgejo (git.jezzahehn.com) - Remove LLM-style language (comprehensive -> full/thorough) - Fix trust listbyusersinit parameter (username -> user_id)
763 lines
15 KiB
Markdown
763 lines
15 KiB
Markdown
# Troubleshooting Guide
|
|
|
|
Common issues and solutions when using the TrustCafé API wrapper.
|
|
|
|
## Table of Contents
|
|
|
|
- [Authentication Issues](#authentication-issues)
|
|
- [Connection Issues](#connection-issues)
|
|
- [Token Management Issues](#token-management-issues)
|
|
- [API Call Issues](#api-call-issues)
|
|
- [Environment Issues](#environment-issues)
|
|
- [Data Handling Issues](#data-handling-issues)
|
|
- [Performance Issues](#performance-issues)
|
|
- [Debugging Strategies](#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:**
|
|
|
|
1. Verify credentials from the admin panel
|
|
2. Ensure environment matches credentials:
|
|
```python
|
|
# Check your credentials are for the right environment
|
|
print(f"Environment: {env}") # Should match where credentials were created
|
|
```
|
|
|
|
3. Generate new credentials if needed:
|
|
- Visit: https://www.trustcafe.io/en/myaccount/apiaccess
|
|
- Click "Create new client credentials key pair"
|
|
- Save the new credentials
|
|
|
|
4. 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:**
|
|
|
|
1. Automatically refresh token:
|
|
```python
|
|
# Check token validity and refresh if needed
|
|
if not API.is_token_valid():
|
|
API.handle_token()
|
|
```
|
|
|
|
2. Pre-load tokens before long operations:
|
|
```python
|
|
# Ensure token is fresh before making many requests
|
|
API.handle_token()
|
|
|
|
# Now all API calls will succeed
|
|
```
|
|
|
|
3. Provide longer expiration time for testing:
|
|
```python
|
|
# 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:**
|
|
|
|
1. Verify scopes on the admin panel
|
|
2. Ensure authentication is enabled in all requests:
|
|
```python
|
|
# 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:**
|
|
|
|
1. Check network connectivity:
|
|
```bash
|
|
# Test connectivity to alpha/production endpoints
|
|
ping alpha.wts2.net
|
|
ping trustcafe.io
|
|
```
|
|
|
|
2. Verify firewall rules allow HTTPS requests
|
|
|
|
3. Try alternative network (mobile hotspot vs. Wi-Fi)
|
|
|
|
4. Check if TrustCafé services are up:
|
|
- Production: https://trustcafe.io
|
|
- Alpha: https://alpha.wts2.net
|
|
|
|
5. Add retry logic:
|
|
```python
|
|
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:**
|
|
|
|
1. Check DNS:
|
|
```bash
|
|
nslookup alpha.wts2.net
|
|
nslookup trustcafe.io
|
|
```
|
|
|
|
2. Try changing DNS server:
|
|
```bash
|
|
# Use Google DNS (8.8.8.8, 8.8.4.4)
|
|
# Or Cloudflare (1.1.1.1, 1.0.0.1)
|
|
```
|
|
|
|
3. Disable VPN temporarily
|
|
4. 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:**
|
|
|
|
1. API `<environment>_handle_token` automatically creates file on first use
|
|
|
|
2. Ensure working directory is writable
|
|
|
|
3. Specify custom token file path:
|
|
```python
|
|
API.handle_token(token_data_path="my/custom/path/token_data.json")
|
|
```
|
|
|
|
4. Manually create token file:
|
|
```python
|
|
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:**
|
|
|
|
1. Ensure writable directory:
|
|
```python
|
|
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")
|
|
```
|
|
|
|
2. Check file permissions:
|
|
```bash
|
|
ls -la token_data_alpha.json
|
|
chmod 644 token_data_alpha.json
|
|
```
|
|
|
|
3. Try with a custom directory:
|
|
```python
|
|
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:**
|
|
|
|
1. Delete corrupted token file:
|
|
```bash
|
|
rm token_data_alpha.json
|
|
```
|
|
|
|
2. Let wrapper recreate it
|
|
|
|
3. Check for concurrent token writes:
|
|
```python
|
|
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:**
|
|
|
|
1. Check parameter requirements in API Reference:
|
|
- See [API Reference](api_reference.md) for each job
|
|
|
|
2. Verify parameter types:
|
|
```python
|
|
# Use correct types
|
|
API.run_job('post.create', {
|
|
"postText": "text string", # Should be string
|
|
"blurLabel": None, # None is okay
|
|
# Wrong: "blurLabel": "" (empty string)
|
|
})
|
|
```
|
|
|
|
3. Verify required parameters:
|
|
```python
|
|
# Example for post.create
|
|
required_fields = ['postText', 'parent']
|
|
|
|
if 'parent' not in data:
|
|
raise ValueError("Required field 'parent' is missing")
|
|
```
|
|
|
|
4. Use debug mode to see request:
|
|
```python
|
|
API = APIClient(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:**
|
|
|
|
1. Verify the path is correct
|
|
2. Check if resource exists:
|
|
```python
|
|
# 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")
|
|
```
|
|
|
|
3. Check for spelling mistakes in paths
|
|
|
|
4. Use debug mode to see exact path being sent:
|
|
```python
|
|
API = APIClient(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:**
|
|
|
|
1. Wait a moment and retry
|
|
2. Check TrustCafé status
|
|
3. Try at a different time
|
|
4. Consider this transient error:
|
|
```python
|
|
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:**
|
|
|
|
1. Implement rate limiting (see main README for example)
|
|
|
|
2. Space out your API calls:
|
|
```python
|
|
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
|
|
```
|
|
|
|
3. Use pagination for large result sets
|
|
|
|
4. 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:**
|
|
|
|
1. Use correct environment names:
|
|
- "alpha" (development/staging)
|
|
- "production" (live)
|
|
|
|
2. Avoid modifying environment mid-session after API init
|
|
|
|
3. Reinitialize if you need to switch:
|
|
```python
|
|
# Create new API client for new environment
|
|
API_prod = APIClient(
|
|
client_id="prod-id",
|
|
client_secret="prod-secret",
|
|
env="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:**
|
|
|
|
1. Check available endpoints in APIClient code
|
|
2. Use correct endpoints: "content", "auth", "audrey", etc.
|
|
3. 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:**
|
|
|
|
1. Add error handling:
|
|
```python
|
|
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}")
|
|
```
|
|
|
|
2. Check if server is responding correctly
|
|
|
|
3. Verify network connectivity
|
|
|
|
4. Check for errors in response:
|
|
```python
|
|
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:**
|
|
|
|
1. Check for empty results:
|
|
```python
|
|
response = API.make_request("GET", "content", "some/path")
|
|
|
|
if 'Items' not in response or not response.get('Items'):
|
|
print("No results found")
|
|
```
|
|
|
|
2. Check pagination status:
|
|
```python
|
|
if 'LastEvaluatedKey' in response:
|
|
print("More results available, need pagination")
|
|
```
|
|
|
|
3. 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:**
|
|
|
|
1. Increase timeout:
|
|
```python
|
|
# 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
|
|
```
|
|
|
|
2. Reduce request complexity
|
|
|
|
3. Implement pagination for large datasets
|
|
|
|
4. 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:**
|
|
|
|
1. Pre-load token:
|
|
```python
|
|
# Get token before doing anything time-sensitive
|
|
API.handle_token()
|
|
|
|
# All subsequent calls will use cached token
|
|
```
|
|
|
|
2. Use manual token for frequent operations:
|
|
```python
|
|
API.set_token({
|
|
"access_token": token,
|
|
"access_token_timeout": 9999999999
|
|
})
|
|
```
|
|
|
|
---
|
|
|
|
## Debugging Strategies
|
|
|
|
### Enable Debug Mode
|
|
|
|
```python
|
|
API = APIClient(
|
|
client_id="your-id",
|
|
client_secret="your-secret",
|
|
env="alpha",
|
|
debug=True # Enables verbose logging
|
|
)
|
|
```
|
|
|
|
This will print:
|
|
- Request method
|
|
- Full URL
|
|
- Headers
|
|
- Request payload
|
|
|
|
### Add Logging
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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
|
|
|
|
```python
|
|
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:
|
|
|
|
1. **Check the Code**: Review the latest version on Forgejo
|
|
- [Forgejo Repository](https://git.jezzahehn.com/KrustyPlanet/trustcafe-api-wrapper)
|
|
|
|
2. **Check TrustCafé Status**: Verify services are up
|
|
- [Production](https://trustcafe.io)
|
|
- [Alpha](https://alpha.wts2.net)
|
|
|
|
3. **Review Contributions**: Check for known issues
|
|
- Open an issue on GitLab
|
|
- Check if a fix is already in progress
|
|
|
|
4. **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.
|