SubtitleEdit/subtitleedit · error · InvalidOperationException
Ollama returned {(int)resp.StatusCode}: {json}
Error message
Ollama returned {(int)resp.StatusCode}: {json} What it means
Thrown by OllamaOcrEngine when the Ollama HTTP `/api/chat` endpoint returns a non-success status code. The message includes the numeric status and the raw JSON body so the caller can see Ollama's own error text. This is an upstream/network failure from the local (or remote) Ollama server, not a seconv bug.
Source
Thrown at src/seconv/Core/OllamaOcrEngine.cs:64
using var data = image.Encode(SKEncodedImageFormat.Png, 90);
var pngBytes = data.ToArray();
var base64 = Convert.ToBase64String(pngBytes);
var prompt = $"Act as a precise OCR engine. Transcribe every line of text from this image exactly as it appears. The language is {_language}. Maintain the vertical order. Use a single '\\n' to separate each line. Do not skip any text. Output only the transcribed text";
var body = "{ \"model\": \"" + Escape(_model) + "\", " +
"\"messages\": [ { \"role\": \"user\", \"content\": \"" + Escape(prompt) + "\", " +
"\"images\": [ \"" + base64 + "\" ] } ], " +
"\"stream\": false }";
using var content = new StringContent(body, Encoding.UTF8);
content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
var resp = _httpClient.PostAsync(_url, content).GetAwaiter().GetResult();
var bodyBytes = resp.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();
var json = Encoding.UTF8.GetString(bodyBytes).Trim();
if (!resp.IsSuccessStatusCode)
{
throw new InvalidOperationException($"Ollama returned {(int)resp.StatusCode}: {json}");
}
var parser = new SeJsonParser();
var contents = parser.GetAllTagsByNameAsStrings(json, "content");
var text = string.Join(string.Empty, contents).Trim();
text = text.Replace("\\n", Environment.NewLine).Replace("\\\"", "\"");
return text.Trim();
}
private static string Escape(string s) =>
s.Replace("\\", "\\\\").Replace("\"", "\\\"").Replace("\n", "\\n").Replace("\r", "\\r");
private static SKBitmap PadToSquare(SKBitmap source)
{
var margin = (int)(Math.Max(source.Width, source.Height) * 0.2);
var side = Math.Max(source.Width, source.Height) + margin;
var info = new SKImageInfo(side, side, SKColorType.Rgba8888, SKAlphaType.Opaque);
var square = new SKBitmap(info);View on GitHub (pinned to 17a9f07487)
Solutions
- Confirm Ollama is up: `curl <ollama-url>/api/tags`.
- Pull the requested model: `ollama pull <model>`.
- Verify `--ollama-url` includes the full base (default usually `http://localhost:11434`).
- Reduce image size or pick a smaller model if Ollama returns 500/OOM.
- Read the JSON body in the error message — it usually states the exact upstream cause.
Example fix
# before seconv in.sup out.srt --ocr-engine ollama --ollama-model llama3.2-vision # -> 'Ollama returned 404: model not found' # after ollama pull llama3.2-vision seconv in.sup out.srt --ocr-engine ollama --ollama-model llama3.2-vision
Defensive patterns
Strategy: retry
Validate before calling
using var ping = new HttpClient { Timeout = TimeSpan.FromSeconds(3) };
var probe = await ping.GetAsync(options.OllamaUrl.TrimEnd('/') + "/api/tags");
if (!probe.IsSuccessStatusCode)
throw new InvalidOperationException("Ollama unreachable at " + options.OllamaUrl); Type guard
static bool IsLikelyOllamaUrl(string? url) =>
!string.IsNullOrWhiteSpace(url) && Uri.TryCreate(url, UriKind.Absolute, out _); Try / catch
for (int attempt = 0; attempt < 3; attempt++)
{
try { return engine.Recognize(bitmap); }
catch (InvalidOperationException ex) when (ex.Message.Contains("Ollama returned") && attempt < 2)
{
await Task.Delay(TimeSpan.FromSeconds(1 << attempt));
continue;
}
} Prevention
- Probe Ollama `/api/tags` and pull the model before starting the batch.
- Add a retry policy for transient 5xx with exponential backoff.
- Surface the JSON body from the error to the user log for diagnosis.
When it happens
Trigger: Calling `OllamaOcrEngine.Recognize` (via `--ocr-engine ollama`) when the POST to `options.OllamaUrl` returns e.g. 404 (model not pulled), 500 (Ollama crashed), 401 (auth on a proxy), or connection-level errors surfaced as non-2xx.
Common situations: Ollama not running (`--ollama-url` pointing at a dead port); the named model not pulled (`ollama pull <model>`); wrong URL base (forgot `/api/chat`); Ollama version too old to support the chat API; GPU/CPU OOM on a large image.
Related errors
- Lens returned a 302 status code twice
- Location header not found
- Lens returned a non-200 status code
- An error occurred calling Cloud Vision API - status code: {r
- llama.cpp returned {(int)resp.StatusCode}: {json}
AI-assisted analysis of SubtitleEdit/subtitleedit@17a9f07487 (2026-08-13).
Data as JSON: /api/errors/e504160a04736bc9.
Report an issue: GitHub.