Troubleshooting
This guide covers common errors and solutions when working with Airbyte Agent Connectors.
Contents
- HTTP Errors
- Retry Configuration
- OAuth Token Refresh Issues
- Common Setup Mistakes
- MCP Server Issues
- Debugging Tips
- SDK Known Issues
- Handling "Already Exists" Errors
- Getting Help
HTTP Errors
401 Unauthorized
Symptoms:
HTTP 401error- "Unauthorized" or "Invalid credentials" message
AuthenticationErrorexception
Causes:
- Invalid API key or token
- Expired OAuth access token
- Wrong credentials for the environment (test vs. production)
Solutions:
Verify credentials are correct:
import os print(f"Token starts with: {os.environ.get('GITHUB_TOKEN', 'NOT SET')[:10]}...")Check for expired OAuth tokens:
- OAuth access tokens typically expire after 1-2 hours
- Ensure refresh token is configured for automatic renewal
# Salesforce with refresh token connector = SalesforceConnector( auth_config=SalesforceOAuthConfig( client_id=os.environ["SF_CLIENT_ID"], client_secret=os.environ["SF_CLIENT_SECRET"], refresh_token=os.environ["SF_REFRESH_TOKEN"] # Required for auto-refresh ) )Regenerate credentials:
- GitHub: Settings > Developer settings > Tokens
- Stripe: Dashboard > Developers > API keys
- Check connector's AUTH.md for credential setup
403 Forbidden
Symptoms:
HTTP 403error- "Forbidden" or "Insufficient permissions" message
- Operation fails despite valid credentials
Causes:
- Token lacks required scopes/permissions
- IP restrictions or firewall rules
- Resource-level access denied
Solutions:
Check token scopes:
- GitHub PAT: Ensure
repo,read:orgscopes for repository access - Slack Bot: Verify required OAuth scopes in app settings
- Stripe: API keys have full access; check for restricted keys
- GitHub PAT: Ensure
Verify resource access:
# Test basic access first result = await connector.execute("viewer", "get", {}) # GitHub result = await connector.execute("balance", "get", {}) # StripeCheck organization/workspace permissions:
- Some resources require admin access
- Organization owners may need to approve OAuth apps
429 Too Many Requests
Symptoms:
HTTP 429error- "Rate limit exceeded" message
RateLimitErrorexception
Causes:
- Exceeded API rate limits
- Too many concurrent requests
- Burst of requests in short time
Solutions:
Wait and retry:
- Connectors have built-in retry with exponential backoff
- Default configuration handles most rate limiting automatically
Check rate limit headers:
# Many APIs return rate limit info in response headers # Check connector logs for rate limit detailsReduce request frequency:
# Add delays between requests import asyncio for item in items: result = await connector.execute("entity", "get", {"id": item}) await asyncio.sleep(0.5) # 500ms delayUse bulk operations:
# Instead of multiple get requests # Use list with filters when possible result = await connector.execute("customers", "list", { "limit": 100, "email": "pattern@example.com" })
5xx Server Errors
Symptoms:
HTTP 500,502,503, or504errors- "Internal Server Error" or "Service Unavailable"
- Intermittent failures
Causes:
- Third-party API outage
- Temporary server issues
- Timeout on long operations
Solutions:
Check service status:
Built-in retry handles transient errors:
- Default retry config: 5 attempts with exponential backoff
- Retries on: 408, 429, 500, 502, 503, 504
Wait and retry manually if needed:
import asyncio async def execute_with_retry(connector, entity, action, params, max_retries=3): for attempt in range(max_retries): result = await connector.execute(entity, action, params) if result.success: return result if "5" in str(result.error)[:3]: # 5xx error await asyncio.sleep(2 ** attempt) # Exponential backoff else: break return result
Retry Configuration
Connectors use automatic retry for transient failures. Default settings:
# Default retry configuration
max_attempts: 5
retry_on_status_codes: [408, 429, 500, 502, 503, 504]
initial_backoff_seconds: 1.0
max_backoff_seconds: 60.0
backoff_multiplier: 2.0
jitter_ratio: 0.1
Retry timeline example:
- Attempt 1: Immediate
- Attempt 2: ~1 second delay
- Attempt 3: ~2 seconds delay
- Attempt 4: ~4 seconds delay
- Attempt 5: ~8 seconds delay
OAuth Token Refresh Issues
Refresh Token Expired
Symptoms:
- Token refresh fails
- "Invalid grant" or "Refresh token expired" error
Solutions:
Re-authorize the application:
- OAuth refresh tokens can expire after extended periods of inactivity
- Complete the OAuth flow again to get new tokens
Check token lifetime settings:
- Salesforce: Refresh tokens expire based on Connected App settings
- Google: Refresh tokens may expire if unused for 6 months
Missing Refresh Token
Symptoms:
- Initial requests work
- Requests fail after access token expires (~1 hour)
Solutions:
Include offline access scope:
- Salesforce: Add
offline_accessto scopes - Google: Add
access_type=offlineto authorization URL
- Salesforce: Add
Store refresh token from initial OAuth:
# Ensure refresh_token is captured during OAuth callback # Store it securely for use in connector configuration
Common Setup Mistakes
Environment Variables Not Loaded
Symptoms:
KeyErrorwhen accessingos.environ- Empty or
Nonecredential values
Solutions:
Load .env file explicitly:
from dotenv import load_dotenv load_dotenv() # Must be called before accessing env vars # Or specify path load_dotenv("/path/to/.env")Check .env file location:
import os print(f"Current directory: {os.getcwd()}") print(f".env exists: {os.path.exists('.env')}")Verify variable names match:
# .env GITHUB_TOKEN=ghp_xxx # Note: no quotes needed # Python os.environ["GITHUB_TOKEN"] # Must match exactly
Wrong Connector Import
Symptoms:
ModuleNotFoundErrororImportError- Attribute errors on connector
Solutions:
Check package is installed:
pip list | grep airbyte-agent # or uv pip list | grep airbyte-agentUse correct import pattern:
# Correct from airbyte_agent_github import GithubConnector from airbyte_agent_github.models import GithubPersonalAccessTokenAuthConfig # Wrong (common mistakes) from airbyte_agent.github import GithubConnector # Wrong path from github_connector import GithubConnector # Wrong module
Async/Await Missing
Symptoms:
RuntimeWarning: coroutine was never awaited- Returns coroutine object instead of result
Solutions:
Always await connector operations:
# Wrong result = connector.execute("customers", "list", {}) # Correct result = await connector.execute("customers", "list", {})Run in async context:
import asyncio async def main(): result = await connector.execute("customers", "list", {}) print(result.data) asyncio.run(main())
Entity/Action Name Errors
Symptoms:
EntityNotFoundErrorActionNotSupportedError
Solutions:
Check exact names in REFERENCE.md:
# Entity names are typically lowercase with underscores "customers" # Correct "Customers" # Wrong (case sensitive) "customer" # Wrong (singular vs plural) "pull_requests" # Correct "pullRequests" # Wrong (camelCase)List available entities:
entities = connector.list_entities() print(entities)
MCP Server Issues
Server Not Starting
Symptoms:
- Claude shows "MCP server not available"
- Connection refused errors
Solutions:
Check uv/Python installation:
uv --version python --version which uvTest server manually:
cd /path/to/airbyte-agent-mcp uv run airbyte_agent_mcpVerify configuration file paths:
ls -la /path/to/airbyte-agent-mcp/configured_connectors.yaml ls -la /path/to/airbyte-agent-mcp/.env
Connector Not Found in MCP
Symptoms:
- "Connector not found" errors
- Connector missing from discovery
Solutions:
Check configured_connectors.yaml:
connectors: - id: stripe # This ID is used in execute calls type: local connector_name: stripe secrets: api_key: STRIPE_API_KEYVerify environment variables are set:
# Check .env has the required variables cat /path/to/airbyte-agent-mcp/.env | grep STRIPERestart MCP server after config changes
Debugging Tips
Enable Verbose Logging
import logging
logging.basicConfig(level=logging.DEBUG)
# Or for specific connector
logging.getLogger("airbyte_agent_github").setLevel(logging.DEBUG)
Inspect Result Objects
result = await connector.execute("customers", "list", {"limit": 1})
print(f"Success: {result.success}")
print(f"Error: {result.error}")
print(f"Data type: {type(result.data)}")
print(f"Data: {result.data}")
print(f"Meta: {result.meta}")
Test Credentials Independently
# Test authentication before complex operations
async def test_auth(connector):
"""Test basic connectivity."""
try:
# Use a simple, low-impact operation
result = await connector.execute("viewer", "get", {}) # GitHub
# or
result = await connector.execute("balance", "get", {}) # Stripe
if result.success:
print("Authentication successful!")
return True
else:
print(f"Auth failed: {result.error}")
return False
except Exception as e:
print(f"Auth error: {e}")
return False
SDK Known Issues
create_hosted() Returns 404
Symptom: Calling create_hosted() fails with HTTP 404.
Cause: SDK bug - uses /v1/integrations/connectors instead of /api/v1/integrations/connectors.
Workaround: Use HTTP API directly:
curl -X POST 'https://api.airbyte.ai/api/v1/integrations/connectors' \
-H 'Authorization: Bearer <TOKEN>' \
-H 'Content-Type: application/json' \
-d '{
"external_user_id": "<WORKSPACE_NAME>",
"workspace_name": "<WORKSPACE_NAME>",
"definition_id": "<DEFINITION_ID>",
"name": "my-connector",
"credentials": {...}
}'
Status: Bug reported upstream. Check SDK version for fix.
"Workspace not found" with external_user_id
Symptom: Error "Workspace not found" when using external_user_id.
Cause: external_user_id must match an existing workspace NAME (not a custom identifier you create).
Fix:
- List workspaces:
GET /api/v1/workspaces - Use the
namefield from an existing workspace - Or create a new workspace first
API Rejects Credentials with Discriminator Fields
Symptom: 400 error when creating connector with auth_type or credentials_title in credentials.
Cause: The API infers auth type from credentials structure. Including discriminator fields like auth_type or credentials_title causes validation failure.
Fix: Remove discriminator fields from credentials:
// WRONG
{"auth_type": "APIKey", "credentials_title": "API Key", "access_key": "...", "access_key_secret": "..."}
// CORRECT
{"access_key": "...", "access_key_secret": "..."}
Handling "Already Exists" Errors
When running the Platform Mode workflow multiple times, you may encounter:
| Error | Cause | Solution |
|---|---|---|
| "Template already exists" | Template with this name registered | Use existing template or choose different name |
| "Connector already exists" | external_user_id already used |
Retrieve existing connector instead of creating |
| "Workspace already exists" | Workspace with this name exists | Use existing workspace |
Retrieving an existing connector:
# If connector was previously created, just reference it:
connector = StripeConnector(
external_user_id="user_123", # Same ID used during creation
airbyte_client_id="...",
airbyte_client_secret="..."
)
# This retrieves the existing connector - no re-auth needed
Getting Help
If you're still experiencing issues:
Check connector-specific docs:
connectors/{connector}/README.mdconnectors/{connector}/AUTH.md
Search existing issues:
Join the community:
Report a bug:
- Include: connector name, operation attempted, error message, Python version
- Create an issue