Error Handling
All API errors return a consistent JSON envelope:
{
"error": {
"code": "ERROR_TYPE",
"message": "Human-readable description",
"details": ["..."]
}
}
HTTP Status Codes
Code |
Meaning |
|---|---|
400 |
Invalid JSON or malformed GeoJSON |
404 |
File or endpoint not found |
422 |
Valid JSON but building attributes fail validation |
500 |
Model execution error or unexpected failure |
Error Categories
VALIDATION_ERRORMissing or out-of-range building attributes (e.g. negative U-value, missing
components).GEOJSON_ERRORStructural problems with the GeoJSON payload (e.g. missing
type,featuresnot an array).MODEL_ERRORThermal solver failure (e.g. LP infeasible, weather file missing).
FILE_ERRORRequested timeseries file not found on disk.
Debugging Checklist
Validate JSON syntax and GeoJSON structure before sending.
Ensure all component U-values are positive and areas > 0.
Check that total window area does not exceed its parent wall area.
Verify
BUEM_WEATHER_DIRis set and the CSV file exists.Review container logs:
docker logs buem-api.Verify file permissions for results directory.
Error Recovery Strategies
Retry Logic
For transient server errors (5xx), implement exponential backoff:
import time
import requests
def api_call_with_retry(url, data, max_retries=3):
for attempt in range(max_retries):
try:
response = requests.post(url, json=data)
if response.status_code < 500:
return response
time.sleep(2 ** attempt)
except requests.RequestException:
time.sleep(2 ** attempt)
return None
Batch Processing Recovery
For large batches, process features individually on errors:
def process_building_batch(buildings):
successful = []
failed = []
# Try batch first
try:
response = api_call({"type": "FeatureCollection", "features": buildings})
return response
except Exception:
# Fall back to individual processing
for building in buildings:
try:
result = api_call({"type": "Feature", **building})
successful.append(result)
except Exception as e:
failed.append({"building": building["id"], "error": str(e)})
return {"successful": successful, "failed": failed}
Validation Pre-check
Validate requests locally before sending to API:
def validate_building_request(feature):
errors = []
# Check required structure
if "properties" not in feature:
errors.append("Missing properties")
attrs = feature.get("properties", {}).get("buem", {}).get("building_attributes", {})
# Check required attributes
required = ["latitude", "longitude", "A_ref", "components"]
for field in required:
if field not in attrs:
errors.append(f"Missing required field: {field}")
# Check numeric ranges
if "latitude" in attrs:
lat = attrs["latitude"]
if not -90 <= lat <= 90:
errors.append(f"Invalid latitude: {lat}")
return errors
Production Considerations
Logging and Monitoring
Log all API responses with status codes
Monitor error rates and patterns
Set up alerts for high error rates or specific error types
Track processing times for performance monitoring
Error Notification
def handle_api_error(response):
if response.status_code >= 400:
error_data = response.json().get("error", {})
# Log structured error data
logger.error("BuEM API Error", extra={
"error_code": error_data.get("code"),
"message": error_data.get("message"),
"details": error_data.get("details"),
"status_code": response.status_code
})
# Send alerts for critical errors
if response.status_code >= 500:
send_alert(f"BuEM API server error: {error_data.get('message')}")
Next Steps
Continue to Integration Examples for complete integration examples showing error handling in practice.