Skip to main content
All Trio API errors return a consistent JSON format:
{
  "error": {
    "code": "NOT_LIVESTREAM",
    "message": "URL is not a live stream",
    "remediation": "This URL points to a video or offline stream..."
  }
}
Use the code field to programmatically handle errors. The remediation field provides actionable guidance.

Stream Errors

These errors occur when there’s a problem with the stream URL or connection.
HTTP Status: 400Message: URL is not a live streamCause: The URL points to a regular video, VOD (past broadcast), or offline stream instead of a live stream.Solution:
  • Verify the stream has a red LIVE badge on YouTube
  • Check that the broadcaster is currently streaming
  • Search YouTube for “live” and filter by “Live” to find active streams
# Test if a URL is live
curl -X POST https://trio.machinefi.com/api/streams/validate \
  -H "Authorization: Bearer YOUR_KEY" \
  -H "Content-Type: application/json" \
  -d '{"stream_url": "YOUR_URL"}'
HTTP Status: 400Message: Invalid URL formatCause: The URL scheme is not supported or the URL is malformed.Solution:
  • Use a valid YouTube URL: https://youtube.com/watch?v=VIDEO_ID
  • Use a valid HLS URL: https://example.com/stream.m3u8
  • Use a valid RTSP URL: rtsp://host:port/path
  • Avoid file://, javascript://, or other unsupported schemes
HTTP Status: 400Message: Failed to fetch streamCause: Unable to connect to or download from the stream URL.Solution:
  • Check if the stream is region-restricted
  • Verify the URL is publicly accessible (not behind auth)
  • Wait a few minutes and retry (may be temporary)
  • Try a different stream to isolate the issue
HTTP Status: 400Message: Stream is offlineCause: The stream was live but has since ended or gone offline.Solution:
  • Check if the broadcaster ended the stream
  • Wait for the stream to come back online
  • Use a different stream
HTTP Status: 400Message: Failed to capture frame from streamCause: Could not extract a video frame from the stream.Solution:
  • The stream may have ended mid-capture
  • Connection may have been interrupted
  • Retry the request
HTTP Status: 400Message: Failed to capture video clip from streamCause: Video clip capture via ffmpeg failed.Solution:
  • Reduce clip_duration_seconds (try 3 instead of 5)
  • Switch to input_mode: "frames" which doesn’t require clip capture
  • Check if the stream supports the required codecs

Job Errors

These errors relate to job creation, management, and lifecycle.
HTTP Status: 429Message: Maximum concurrent jobs reachedCause: You have 10 active jobs running simultaneously (the limit).Solution:
# List your active jobs
curl https://trio.machinefi.com/api/jobs \
  -H "Authorization: Bearer YOUR_KEY"

# Cancel a job to free up a slot
curl -X DELETE https://trio.machinefi.com/api/jobs/JOB_ID \
  -H "Authorization: Bearer YOUR_KEY"
HTTP Status: 404Message: Job not foundCause: The job ID doesn’t exist or has been cleaned up.Solution:
  • Jobs are removed 1 hour after completion
  • Verify the job ID is correct (UUIDs are case-sensitive)
  • Use GET /jobs to list your active jobs
HTTP Status: 400Message: Job is already stoppedCause: Attempted to cancel a job that’s already completed, failed, or stopped.Solution:
  • No action needed - the job has already ended
  • Check job status with GET /jobs/{id} to see final stats

Validation Errors

These errors occur when request parameters are invalid.
HTTP Status: 422Message: Invalid request parametersCause: Required fields are missing or have invalid values.Solution:
  • Check that stream_url is provided and non-empty
  • Check that condition is provided (for check-once and live-monitor)
  • Verify numeric fields are within allowed ranges:
    • interval_seconds: 5-300
    • window_minutes: 1-60
    • clip_duration_seconds: 1-10
HTTP Status: 400Message: Invalid input mode configurationCause: Using clip or hybrid mode without a Gemini model.Solution:
  • Use input_mode: "frames" (works with any model)
  • Or ensure you’re using a Gemini model (default is gemini-2.0-flash)
{
  "stream_url": "...",
  "condition": "...",
  "input_mode": "frames"
}
HTTP Status: 400Message: Invalid requestCause: General request error that doesn’t fit other categories.Solution:
  • Check request body is valid JSON
  • Verify Content-Type header is application/json
  • Review the error message for specific details

Authentication Errors

These errors relate to API authentication and authorization.
HTTP Status: 401Message: Authentication requiredCause: Missing or invalid API key.Solution:
# Correct format
curl -X POST https://trio.machinefi.com/api/check-once \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"stream_url": "...", "condition": "..."}'
Common mistakes:
  • Missing Bearer prefix
  • Extra spaces in the header
  • Using wrong header name (API-Key instead of Authorization)
HTTP Status: 403Message: Access deniedCause: Endpoint requires special permissions or internal access.Solution:
  • Some endpoints like /logs and /metrics are internal-only
  • Check the API documentation for access requirements

Server Errors

These errors indicate server-side issues.
HTTP Status: 500Message: Internal server errorCause: Unexpected server error.Solution:
HTTP Status: 500Message: Vision model analysis failedCause: The AI model failed to analyze the stream content.Solution:
  • This is usually temporary - retry the request
  • Try a different stream to isolate the issue
  • If persistent, the VLM provider may be experiencing issues
HTTP Status: 400 (in job status)Message: Failed to deliver webhookCause: Webhook delivery failed after 3 retries.Solution:
  • Ensure your webhook URL is publicly accessible
  • Your endpoint must respond within 30 seconds
  • Return a 2xx status code to acknowledge receipt
  • Test with webhook.site first

Error Handling Best Practices

1. Check the error code, not the message

response = requests.post(...)
if response.status_code != 200:
    error = response.json()["error"]

    if error["code"] == "NOT_LIVESTREAM":
        # Handle non-live stream
        print("Please use a live stream URL")
    elif error["code"] == "MAX_JOBS_REACHED":
        # Cancel oldest job and retry
        cancel_oldest_job()
        retry_request()
    else:
        # Log and show remediation
        print(f"Error: {error['remediation']}")

2. Implement retry logic for transient errors

RETRYABLE_ERRORS = ["STREAM_FETCH_FAILED", "VLM_ERROR", "INTERNAL_ERROR"]

for attempt in range(3):
    response = make_request()
    if response.status_code == 200:
        break

    error_code = response.json()["error"]["code"]
    if error_code not in RETRYABLE_ERRORS:
        break  # Don't retry non-transient errors

    time.sleep(2 ** attempt)  # Exponential backoff

3. Use the /streams/validate endpoint first

Before starting a long-running job, validate the stream:
# Validate before monitoring
curl -X POST https://trio.machinefi.com/api/streams/validate \
  -H "Authorization: Bearer YOUR_KEY" \
  -d '{"stream_url": "YOUR_URL"}'
This catches NOT_LIVESTREAM and INVALID_URL errors early.