Skip to content

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:

  1. Missing API key header
  2. Incorrect key format
  3. Key not in database
  4. Key revoked

Solutions:

bash
# 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:

bash
# 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:

  1. Undefined values in query bindings
  2. Schema mismatch
  3. Constraint violations

Solutions:

typescript
// 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:

bash
# 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:

bash
# 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:

bash
# 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:

bash
# 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-images

Provider 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:

  1. Invalid Gemini API key
  2. Safety filter triggered
  3. API quota exceeded
  4. Service unavailable

Solutions:

bash
# 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:

  1. Tenant has not added an OpenAI key in tenant_provider_credentials
  2. openai-gpt-image-2 not in tenant's allowedModels (request is rejected)
  3. Organization Verification not completed on the OpenAI side
  4. Size violates constraints (max edge 3840, multiples of 16, ≤3:1 aspect, 655K–8.3M pixels)
  5. output_compression set on a PNG output
  6. Quality tier high at 4K hit the 240s provider timeout

Solutions:

bash
# 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:

  1. Review and modify prompt
  2. Use negative prompts to exclude problematic content
  3. Check Gemini safety settings

Rate Limiting Issues ​

"Rate limit exceeded" ​

Symptoms:

  • 429 Too Many Requests
  • Retry-After header in response

Solutions:

bash
# 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:

bash
# 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:

bash
# 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:

bash
# Check migrations in wrangler.jsonc
{
  "migrations": [
    {
      "tag": "v3",
      "new_sqlite_classes": ["GoBananasMcpAgent"]
    }
  ]
}

# Redeploy to apply migrations
npm run deploy

Secrets not available ​

Symptoms:

  • Encryption fails
  • Undefined environment variables

Solutions:

bash
# List secrets
wrangler secret list

# Re-set secrets
wrangler secret put ENCRYPTION_KEY
wrangler secret put ADMIN_TOKEN

# Verify in logs
npm run tail

Session Issues ​

"No image to edit" ​

Symptoms:

  • continue_editing fails
  • Error code: NO_IMAGE_TO_EDIT

Solutions:

bash
# 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_id

Session not persisting ​

Symptoms:

  • Last image ID not updating
  • Session data lost between requests

Solutions:

Check Durable Object routing:

typescript
// 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_character fails
  • Character lookup returns null

Solutions:

bash
# 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:

  1. Add more reference images (2-3 recommended)
  2. Improve base_prompt with specific visual details
  3. Use consistent style presets
  4. Avoid scene elements in base_prompt

Logging and Debugging ​

Enable Debug Logs ​

jsonc
{
  "vars": {
    "LOG_LEVEL": "debug"
  }
}

Inspect Request/Response ​

bash
# 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 ​

bash
# 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 ​

ErrorCauseSolution
ENCRYPTION_KEY not setMissing secretwrangler secret put ENCRYPTION_KEY
Invalid API key formatKey doesn't match patternCheck key starts with sk_live_ or sk_test_
Tenant not foundInvalid tenant_idVerify tenant exists in database
Failed to decryptWrong encryption keyVerify ENCRYPTION_KEY matches encryption
R2 upload failedBucket misconfiguredCheck bucket exists and permissions
D1 constraint violationDuplicate or invalid dataCheck unique constraints

Getting Help ​

If issues persist:

  1. Check GitHub Issues
  2. Search error message in issues
  3. Open new issue with:
    • Error message
    • Steps to reproduce
    • Relevant logs
    • Configuration (without secrets)

Next Steps ​

Released under the MIT License.