Error Handling
Understanding and handling errors from the BioQuery API.
Error Response Format
All errors return a consistent JSON structure:
{
"error": "error_code",
"message": "Human-readable description",
"details": { ... }
}Error Codes
Authentication Errors
unauthorized
{
"error": "unauthorized",
"message": "Invalid or missing API key"
}HTTP Status: 401
Causes:
- Missing
Authorizationheader - Invalid API key format
- Revoked or expired key
Solution: Check your API key and ensure it’s correctly formatted in the Authorization header.
forbidden
{
"error": "forbidden",
"message": "API access not enabled for this account"
}HTTP Status: 403
Cause: Your account doesn’t have API access.
Solution: Contact us to request Researcher access.
Query Errors
invalid_query
{
"error": "invalid_query",
"message": "Could not parse the query",
"details": {
"suggestion": "Try using specific gene symbols (e.g., TP53) and cancer type codes (e.g., BRCA)"
}
}HTTP Status: 400
Causes:
- Ambiguous or unclear question
- Missing gene or cancer type
- Unsupported query type
Solution: Rephrase your query with specific gene symbols and cancer type codes.
unknown_gene
{
"error": "unknown_gene",
"message": "Gene 'XYZ123' not found in database",
"details": {
"queried": "XYZ123",
"suggestions": ["XYZ1", "XYZ2"]
}
}HTTP Status: 400
Cause: The gene symbol isn’t in our database.
Solution: Check spelling or use the genes endpoint to search for valid symbols.
unknown_cancer_type
{
"error": "unknown_cancer_type",
"message": "Cancer type 'lung' is ambiguous",
"details": {
"queried": "lung",
"suggestions": [
{"code": "LUAD", "name": "Lung adenocarcinoma"},
{"code": "LUSC", "name": "Lung squamous cell carcinoma"}
]
}
}HTTP Status: 400
Cause: The cancer type is ambiguous or not recognized.
Solution: Use a specific TCGA cancer type code.
no_data
{
"error": "no_data",
"message": "No expression data available for DDR1 in CHOL",
"details": {
"gene": "DDR1",
"cancer_type": "CHOL",
"sample_count": 0
}
}HTTP Status: 404
Cause: The requested combination of gene and cancer type has no data.
Solution: Try a different cancer type or verify the gene is expressed in that tissue.
Rate Limiting
rate_limited
{
"error": "rate_limited",
"message": "Rate limit exceeded",
"details": {
"limit": 100,
"remaining": 0,
"reset_at": "2024-01-15T11:00:00Z"
}
}HTTP Status: 429
Cause: You’ve exceeded your rate limit.
Solution: Wait until the reset time, or contact us for higher limits.
Headers included:
X-RateLimit-Limit: Your daily limitX-RateLimit-Remaining: Requests remainingX-RateLimit-Reset: Unix timestamp of reset
Server Errors
internal_error
{
"error": "internal_error",
"message": "An unexpected error occurred",
"details": {
"request_id": "req_abc123"
}
}HTTP Status: 500
Cause: Something went wrong on our end.
Solution: Retry the request. If it persists, contact support with the request_id.
Handling Errors in Code
Python
from bioquery import BioQuery, BioQueryError, RateLimitError
client = BioQuery(api_key="YOUR_API_KEY")
try:
result = client.query("Is DDR1 higher in KIRP vs KIRC?")
except RateLimitError as e:
print(f"Rate limited. Reset at: {e.reset_at}")
except BioQueryError as e:
print(f"Error: {e.message}")
if e.details:
print(f"Details: {e.details}")JavaScript
const BioQuery = require('bioquery');
const client = new BioQuery({ apiKey: 'YOUR_API_KEY' });
try {
const result = await client.query('Is DDR1 higher in KIRP vs KIRC?');
} catch (error) {
if (error.code === 'rate_limited') {
console.log(`Rate limited until ${error.details.reset_at}`);
} else {
console.error(`Error: ${error.message}`);
}
}Retry Strategy
For transient errors (500, 502, 503, 504), implement exponential backoff:
import time
import random
def query_with_retry(client, query, max_retries=3):
for attempt in range(max_retries):
try:
return client.query(query)
except InternalError:
if attempt == max_retries - 1:
raise
wait = (2 ** attempt) + random.random()
time.sleep(wait)Always include the request_id from error responses when contacting support. This helps us debug issues quickly.