{"record":{"id":"e504160a04736bc9","repo":"SubtitleEdit/subtitleedit","slug":"ollama-returned-int-resp-statuscode-json","errorCode":null,"errorMessage":"Ollama returned {(int)resp.StatusCode}: {json}","messagePattern":"Ollama returned (.+?): (.+?)","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"error","filePath":"src/seconv/Core/OllamaOcrEngine.cs","lineNumber":64,"sourceCode":"        using var data = image.Encode(SKEncodedImageFormat.Png, 90);\n        var pngBytes = data.ToArray();\n        var base64 = Convert.ToBase64String(pngBytes);\n\n        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\";\n        var body = \"{ \\\"model\\\": \\\"\" + Escape(_model) + \"\\\", \" +\n                   \"\\\"messages\\\": [ { \\\"role\\\": \\\"user\\\", \\\"content\\\": \\\"\" + Escape(prompt) + \"\\\", \" +\n                   \"\\\"images\\\": [ \\\"\" + base64 + \"\\\" ] } ], \" +\n                   \"\\\"stream\\\": false }\";\n\n        using var content = new StringContent(body, Encoding.UTF8);\n        content.Headers.ContentType = MediaTypeHeaderValue.Parse(\"application/json\");\n\n        var resp = _httpClient.PostAsync(_url, content).GetAwaiter().GetResult();\n        var bodyBytes = resp.Content.ReadAsByteArrayAsync().GetAwaiter().GetResult();\n        var json = Encoding.UTF8.GetString(bodyBytes).Trim();\n        if (!resp.IsSuccessStatusCode)\n        {\n            throw new InvalidOperationException($\"Ollama returned {(int)resp.StatusCode}: {json}\");\n        }\n\n        var parser = new SeJsonParser();\n        var contents = parser.GetAllTagsByNameAsStrings(json, \"content\");\n        var text = string.Join(string.Empty, contents).Trim();\n        text = text.Replace(\"\\\\n\", Environment.NewLine).Replace(\"\\\\\\\"\", \"\\\"\");\n        return text.Trim();\n    }\n\n    private static string Escape(string s) =>\n        s.Replace(\"\\\\\", \"\\\\\\\\\").Replace(\"\\\"\", \"\\\\\\\"\").Replace(\"\\n\", \"\\\\n\").Replace(\"\\r\", \"\\\\r\");\n\n    private static SKBitmap PadToSquare(SKBitmap source)\n    {\n        var margin = (int)(Math.Max(source.Width, source.Height) * 0.2);\n        var side = Math.Max(source.Width, source.Height) + margin;\n        var info = new SKImageInfo(side, side, SKColorType.Rgba8888, SKAlphaType.Opaque);\n        var square = new SKBitmap(info);","sourceCodeStart":46,"sourceCodeEnd":82,"githubUrl":"https://github.com/SubtitleEdit/subtitleedit/blob/17a9f0748781032255db3526b7215d2fb891e3af/src/seconv/Core/OllamaOcrEngine.cs#L46-L82","documentation":"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.","triggerScenarios":"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.","commonSituations":"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.","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."],"exampleFix":"# before\nseconv in.sup out.srt --ocr-engine ollama --ollama-model llama3.2-vision\n#  -> 'Ollama returned 404: model not found'\n# after\nollama pull llama3.2-vision\nseconv in.sup out.srt --ocr-engine ollama --ollama-model llama3.2-vision","handlingStrategy":"retry","validationCode":"using var ping = new HttpClient { Timeout = TimeSpan.FromSeconds(3) };\nvar probe = await ping.GetAsync(options.OllamaUrl.TrimEnd('/') + \"/api/tags\");\nif (!probe.IsSuccessStatusCode)\n    throw new InvalidOperationException(\"Ollama unreachable at \" + options.OllamaUrl);","typeGuard":"static bool IsLikelyOllamaUrl(string? url) =>\n    !string.IsNullOrWhiteSpace(url) && Uri.TryCreate(url, UriKind.Absolute, out _);","tryCatchPattern":"for (int attempt = 0; attempt < 3; attempt++)\n{\n    try { return engine.Recognize(bitmap); }\n    catch (InvalidOperationException ex) when (ex.Message.Contains(\"Ollama returned\") && attempt < 2)\n    {\n        await Task.Delay(TimeSpan.FromSeconds(1 << attempt));\n        continue;\n    }\n}","preventionTips":["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."],"tags":["ocr","ollama","network","http","external-service","llm"],"backgroundTag":null,"analyzedSha":"17a9f0748781032255db3526b7215d2fb891e3af","analyzedAt":"2026-08-13T18:11:43.374Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}