Troubleshooting - DrHazemAli/AzureSoraSDK GitHub Wiki
This guide helps you resolve common issues when using the AzureSoraSDK.
Symptoms:
-
SoraAuthenticationException
thrown - HTTP 401 or 403 responses
Solutions:
-
Verify API Key
// Check if API key is set correctly Console.WriteLine($"API Key starts with: {apiKey.Substring(0, 4)}...");
-
Check Endpoint URL
// Ensure endpoint is correct format // Correct: https://your-resource.openai.azure.com // Wrong: https://your-resource.openai.azure.com/
-
Verify Deployment Exists
- Log into Azure Portal
- Navigate to your Azure OpenAI resource
- Check that the deployment name matches
-
Check Permissions
- Ensure your API key has "Cognitive Services OpenAI User" role
- Verify resource is not in a private network
Solution:
// Ensure dimensions are divisible by 8
int width = 1920; // ✓ Divisible by 8
int height = 1080; // ✓ Divisible by 8
// Helper function
int RoundToNearest8(int value)
{
return (int)Math.Round(value / 8.0) * 8;
}
Solution:
// Validate duration
int duration = Math.Max(1, Math.Min(60, requestedDuration));
Solution:
// Validate prompt
if (string.IsNullOrWhiteSpace(prompt))
{
throw new ArgumentException("Prompt is required");
}
Symptoms:
-
SoraRateLimitException
thrown - HTTP 429 responses
Solutions:
-
Implement Exponential Backoff
int retryCount = 0; while (retryCount < 3) { try { return await SubmitVideoJobAsync(...); } catch (SoraRateLimitException ex) { if (ex.RetryAfter.HasValue) { await Task.Delay(ex.RetryAfter.Value); } else { await Task.Delay(TimeSpan.FromSeconds(Math.Pow(2, retryCount))); } retryCount++; } }
-
Implement Request Queuing
public class RateLimitedQueue { private readonly SemaphoreSlim _semaphore = new(5); // 5 concurrent requests public async Task<T> ExecuteAsync<T>(Func<Task<T>> operation) { await _semaphore.WaitAsync(); try { return await operation(); } finally { _semaphore.Release(); } } }
Symptoms:
-
SoraTimeoutException
thrown - Jobs taking longer than expected
Solutions:
-
Increase Timeout Configuration
{ "AzureSora": { "HttpTimeout": "00:15:00", "MaxWaitTime": "01:00:00" } }
-
Check Job Status Separately
try { var videoUrl = await WaitForCompletionAsync(jobId, maxWaitTime: TimeSpan.FromMinutes(5)); } catch (SoraTimeoutException) { // Continue checking status manually var status = await GetJobStatusAsync(jobId); if (status.Status == JobStatus.Running) { // Job is still processing, check again later } }
Solutions:
-
Check Internet Connection
try { var client = new HttpClient(); var response = await client.GetAsync("https://www.microsoft.com"); Console.WriteLine($"Network check: {response.IsSuccessStatusCode}"); } catch (Exception ex) { Console.WriteLine($"Network issue: {ex.Message}"); }
-
Configure Proxy Settings
services.AddHttpClient<ISoraClient, SoraClient>() .ConfigurePrimaryHttpMessageHandler(() => new HttpClientHandler { Proxy = new WebProxy("http://proxy.company.com:8080"), UseProxy = true });
Symptoms:
-
SoraNotFoundException
thrown - Job ID doesn't exist
Possible Causes:
- Job ID is incorrect
- Job has expired (older than retention period)
- Wrong Azure OpenAI resource
Solution:
// Store job IDs immediately after creation
var jobId = await SubmitVideoJobAsync(...);
await SaveJobIdToDatabase(jobId);
// Verify job ID format
if (!Regex.IsMatch(jobId, @"^[a-zA-Z0-9\-]+$"))
{
throw new ArgumentException("Invalid job ID format");
}
The SDK now supports all Azure job status values:
Status | JobStatus Enum | Description |
---|---|---|
queued |
Pending |
Job is waiting to start |
preprocessing |
Running |
Job is preparing |
running |
Running |
Job is actively processing |
processing |
Running |
Job is in final processing |
succeeded |
Succeeded |
Job completed successfully |
failed |
Failed |
Job failed |
cancelled |
Cancelled |
Job was cancelled |
When a job succeeds, the video URL is constructed from the generation ID:
var status = await client.GetJobStatusAsync(jobId);
if (status.Status == JobStatus.Succeeded)
{
// Video URL is automatically constructed
Console.WriteLine($"Video URL: {status.VideoUrl}");
// The URL format is:
// {endpoint}/openai/v1/video/generations/{generationId}/content/video?api-version={version}
}
// Configure logging
services.AddLogging(builder =>
{
builder.SetMinimumLevel(LogLevel.Debug);
builder.AddConsole();
builder.AddDebug();
builder.AddFilter("AzureSoraSDK", LogLevel.Trace);
});
services.AddHttpClient<ISoraClient, SoraClient>()
.AddHttpMessageHandler(() => new LoggingHandler());
public class LoggingHandler : DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request,
CancellationToken cancellationToken)
{
Console.WriteLine($"Request: {request.Method} {request.RequestUri}");
var response = await base.SendAsync(request, cancellationToken);
Console.WriteLine($"Response: {response.StatusCode}");
return response;
}
}
try
{
var jobId = await client.SubmitVideoJobAsync(...);
}
catch (SoraException ex)
{
Console.WriteLine($"Error Code: {ex.ErrorCode}");
Console.WriteLine($"Status Code: {ex.StatusCode}");
Console.WriteLine($"Message: {ex.Message}");
// Log full exception details
File.WriteAllText("error_log.txt", ex.ToString());
}
Solutions:
-
Optimize Video Parameters
// Lower resolution for faster generation var jobId = await client.SubmitVideoJobAsync( prompt: "Simple test prompt", width: 640, height: 480, nSeconds: 5 // Shorter duration );