Troubleshooting
Common issues and solutions for Go Bananas! deployments.
Authentication Issues
"Invalid or missing API key"
Symptoms:
- 401 Unauthorized response
- Error code:
AUTHENTICATION_ERROR
Causes:
- Missing API key header
- Incorrect key format
- Key not in database
- Key revoked
Solutions:
# Verify key format (should be sk_live_xxx or sk_test_xxx)
echo $API_KEY | grep -E '^sk_(live|test)_[a-zA-Z0-9]{32,}$'
# Keys are stored only as SHA-256 hashes, so look them up by hash
HASH=$(printf '%s' "$API_KEY" | shasum -a 256 | cut -d' ' -f1)
# Check key exists and is active
wrangler d1 execute go-bananas-db --command \
"SELECT tenant_id, key_name, is_active FROM api_keys WHERE api_key LIKE 'sha256:$HASH:%'"
# (A key created before hashing, not yet used since, is still stored in plain text.)
# Test with curl
curl -X GET "https://gobananasai.com/api/profile" \
-H "X-API-Key: sk_live_xxx" \
-v"Tenant account is inactive"
Symptoms:
- 403 Forbidden response
- Valid API key but access denied
Solutions:
# Check tenant status
wrangler d1 execute go-bananas-db --command \
"SELECT is_active FROM tenants WHERE tenant_id = 'your-tenant'"
# Reactivate tenant
curl -X PATCH "https://gobananasai.com/admin/tenants/your-tenant" \
-H "X-Admin-Token: admin_token" \
-d '{"isActive": true}'Database Issues
"D1_TYPE_ERROR" or "D1_EXEC_ERROR"
Symptoms:
- 500 Internal Server Error
- D1 execution fails
Common Causes:
- Undefined values in query bindings
- Schema mismatch
- Constraint violations
Solutions:
// WRONG - undefined causes D1_TYPE_ERROR
const result = await db.prepare('SELECT * FROM images LIMIT ?')
.bind(input.limit) // input.limit might be undefined
.all();
// CORRECT - use null coalescing
const result = await db.prepare('SELECT * FROM images LIMIT ?')
.bind(input.limit ?? 50)
.all();Check schema:
# Verify table exists
wrangler d1 execute go-bananas-db --command \
"SELECT sql FROM sqlite_master WHERE name = 'images'"
# Check for missing columns
wrangler d1 execute go-bananas-db --command \
"PRAGMA table_info(images)""Database not found"
Symptoms:
- Worker can't connect to D1
Solutions:
# Verify database exists
wrangler d1 list
# Check wrangler.jsonc has correct ID
# Verify binding name matches code (DB)Storage Issues
"Image not found" (R2)
Symptoms:
- 404 when accessing image URL
- Image metadata exists but file missing
Solutions:
# Check if object exists
wrangler r2 object get go-bananas-images {r2_key}
# Verify public URL configuration
curl -I "https://pub-xxx.r2.dev/{r2_key}"
# Check CORS
wrangler r2 bucket cors list go-bananas-images"Failed to store image"
Symptoms:
- Upload fails
- Storage error in logs
Solutions:
# Check bucket exists
wrangler r2 bucket list
# Test write access
echo "test" | wrangler r2 object put go-bananas-images test.txt
# Check bucket quota (if applicable)
wrangler r2 bucket info go-bananas-imagesProvider API Issues
Generation routes to whichever provider matches the request's model_id. Each provider has its own failure modes — check both the model and the tenant credential before assuming the registry is broken.
"Image generation failed" (Gemini)
Symptoms:
- 502 Bad Gateway
- Error code:
GEMINI_API_ERROR
Common Causes:
- Invalid Gemini API key
- Safety filter triggered
- API quota exceeded
- Service unavailable
Solutions:
# Test the Gemini key directly (lists the models it can use; no image is generated)
curl "https://generativelanguage.googleapis.com/v1beta/models" \
-H "x-goog-api-key: YOUR_GEMINI_KEY"
# A 200 response means the key works; look for the image models in the list
# Check API key validity
# Go to https://aistudio.google.com/apikey
# Update tenant's Gemini key
curl -X PATCH "https://gobananasai.com/admin/tenants/your-tenant" \
-H "X-Admin-Token: admin_token" \
-d '{"geminiApiKey": "new-key"}'"Image generation failed" (OpenAI gpt-image-2)
Symptoms:
- 502 Bad Gateway
- Error code:
OPENAI_API_ERROR - Circuit breaker open after 5 consecutive failures
Common Causes:
- Tenant has not added an OpenAI key in
tenant_provider_credentials openai-gpt-image-2not in tenant'sallowedModels(request is rejected)- Organization Verification not completed on the OpenAI side
- Size violates constraints (max edge 3840, multiples of 16, ≤3:1 aspect, 655K–8.3M pixels)
output_compressionset on a PNG output- Quality tier
highat 4K hit the 240s provider timeout
Solutions:
# Test OpenAI API directly
curl "https://api.openai.com/v1/images/generations" \
-H "Authorization: Bearer $OPENAI_KEY" \
-H "Content-Type: application/json" \
-d '{"model":"gpt-image-2","prompt":"a red apple","size":"1024x1024"}'
# Verify the tenant has the model on their allowlist
sqlite3 d1.db "SELECT allowed_models FROM tenants WHERE tenant_id='your-tenant';"
# Verify provider credential is set
sqlite3 d1.db "SELECT provider FROM tenant_provider_credentials WHERE tenant_id='your-tenant';"Circuit breaker
Each OpenAI key has its own CircuitBreaker keyed on the first 16 chars. When it trips (5 consecutive failures), subsequent requests fail fast for 30s. check_quota returns the breaker state so you can detect this without making a real generation call.
"Content blocked by safety filters"
Symptoms:
- Generation fails for certain prompts
- Safety filter error in response
Solutions:
- Review and modify prompt
- Use negative prompts to exclude problematic content
- Check Gemini safety settings
Rate Limiting Issues
"Rate limit exceeded"
Symptoms:
- 429 Too Many Requests
Retry-Afterheader in response
Solutions:
# Check current rate limit
curl "https://gobananasai.com/api/usage/rate-limit" \
-H "X-API-Key: sk_live_xxx"
# Increase tenant rate limit
curl -X PATCH "https://gobananasai.com/admin/tenants/your-tenant" \
-H "X-Admin-Token: admin_token" \
-d '{"rateLimitPerMinute": 120}'"Monthly quota exceeded"
Symptoms:
- 402 Payment Required
- Error code:
QUOTA_EXCEEDED
Solutions:
# Check current usage
curl "https://gobananasai.com/api/usage" \
-H "X-API-Key: sk_live_xxx"
# Increase quota
curl -X PATCH "https://gobananasai.com/admin/tenants/your-tenant" \
-H "X-Admin-Token: admin_token" \
-d '{"monthlyQuotaMb": 20480}'
# Or delete unused images
curl -X POST "https://gobananasai.com/api/images/delete-bulk" \
-H "X-API-Key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"ids": [1, 2, 3, 4, 5]}'Deployment Issues
"Worker not found"
Symptoms:
- 404 on all endpoints
- Deployment seems to fail
Solutions:
# Check deployment status
wrangler deployments list
# Verify worker name
wrangler whoami
# Redeploy
npm run deploy"Durable Object not found"
Symptoms:
- MCP endpoints fail
- Error about missing class
Solutions:
# Check migrations in wrangler.jsonc
{
"migrations": [
{
"tag": "v3",
"new_sqlite_classes": ["GoBananasMcpAgent"]
}
]
}
# Redeploy to apply migrations
npm run deploySecrets not available
Symptoms:
- Encryption fails
- Undefined environment variables
Solutions:
# List secrets
wrangler secret list
# Re-set secrets
wrangler secret put ENCRYPTION_KEY
wrangler secret put ADMIN_TOKEN
# Verify in logs
npm run tailSession Issues
"No image to edit"
Symptoms:
continue_editingfails- Error code:
NO_IMAGE_TO_EDIT
Solutions:
# Check session state
wrangler d1 execute go-bananas-db --command \
"SELECT * FROM sessions WHERE session_id = 'your-session'"
# Generate an image first, then edit
# Or use edit_image with explicit image_idSession not persisting
Symptoms:
- Last image ID not updating
- Session data lost between requests
Solutions:
Check Durable Object routing:
// Ensure session ID is consistent
const sessionId = request.headers.get('X-Session-Id')
|| `sess_${crypto.randomUUID()}`;Character Reference Issues
"Character not found"
Symptoms:
generate_with_characterfails- Character lookup returns null
Solutions:
# Check character exists
wrangler d1 execute go-bananas-db --command \
"SELECT * FROM characters WHERE tenant_id = 'your-tenant' AND character_name = 'Luna'"
# Check reference image IDs are valid
wrangler d1 execute go-bananas-db --command \
"SELECT id FROM images WHERE id IN (12, 15, 18) AND tenant_id = 'your-tenant'"Inconsistent character appearance
Solutions:
- Add more reference images (2-3 recommended)
- Improve base_prompt with specific visual details
- Use consistent style presets
- Avoid scene elements in base_prompt
Logging and Debugging
Enable Debug Logs
{
"vars": {
"LOG_LEVEL": "debug"
}
}Inspect Request/Response
# View real-time logs
wrangler tail --format pretty
# Filter for errors
wrangler tail --filter "error"
# Filter for specific tenant
wrangler tail --search "acme-corp"Test MCP Protocol
# List available tools
curl -X POST "https://mcp.gobananasai.com" \
-H "X-API-Key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{"jsonrpc": "2.0", "method": "tools/list", "id": 1}'
# Call specific tool
curl -X POST "https://mcp.gobananasai.com" \
-H "X-API-Key: sk_live_xxx" \
-H "Content-Type: application/json" \
-d '{
"jsonrpc": "2.0",
"method": "tools/call",
"params": {
"name": "get_help",
"arguments": {}
},
"id": 1
}'Common Error Messages
| Error | Cause | Solution |
|---|---|---|
ENCRYPTION_KEY not set | Missing secret | wrangler secret put ENCRYPTION_KEY |
Invalid API key format | Key doesn't match pattern | Check key starts with sk_live_ or sk_test_ |
Tenant not found | Invalid tenant_id | Verify tenant exists in database |
Failed to decrypt | Wrong encryption key | Verify ENCRYPTION_KEY matches encryption |
R2 upload failed | Bucket misconfigured | Check bucket exists and permissions |
D1 constraint violation | Duplicate or invalid data | Check unique constraints |
Getting Help
If issues persist:
- Check GitHub Issues
- Search error message in issues
- Open new issue with:
- Error message
- Steps to reproduce
- Relevant logs
- Configuration (without secrets)