{"record":{"id":"b433e5aa88b5d26b","repo":"babalae/better-genshin-impact","slug":"error-b433e5","errorCode":null,"errorMessage":"没有可用的上一步识别位置，无法执行隐式坐标操作","messagePattern":"没有可用的上一步识别位置，无法执行隐式坐标操作","errorType":"exception","errorClass":"InvalidOperationException","httpStatus":null,"severity":"warning","filePath":"BetterGenshinImpact/Core/BgiVision/BvFlow.cs","lineNumber":492,"sourceCode":"            throw new InvalidOperationException(\"添加流程步骤后不能修改流程默认配置\");\n        }\n    }\n\n    private sealed record BvFlowStep(string Description, Func<BvFlowExecutionContext, Task> Action);\n\n}\n\ninternal sealed record BvFlowConditionResult(bool Succeeded, Region? Match);\n\ninternal sealed class BvFlowExecutionContext\n{\n    public Rect? LastMatchRect { get; set; }\n\n    public (double X, double Y) GetLastMatchCenter()\n    {\n        if (LastMatchRect is not { } rect)\n        {\n            throw new InvalidOperationException(\"没有可用的上一步识别位置，无法执行隐式坐标操作\");\n        }\n\n        return (rect.X + rect.Width / 2d, rect.Y + rect.Height / 2d);\n    }\n}\n\ninternal sealed class BvFlowServices\n{\n    public required Action ThrowIfCancellationRequested { get; set; }\n    public required Func<IReadOnlyList<BvLocator>, BvFlowCondition, BvFlowConditionResult> FindTargets { get; set; }\n    public required Func<Region, Rect> GetMatchRect { get; set; }\n    public required Func<int, Task> Delay { get; set; }\n    public required Func<long> GetTimestamp { get; set; }\n    public required Func<long, double> GetElapsedMilliseconds { get; set; }\n    public required Action<Vanara.PInvoke.User32.VK> KeyPress { get; set; }\n    public required Action<double, double> LeftClick { get; set; }\n    public required Action<double, double> RightClick { get; set; }\n    public required Action<double, double> MiddleClick { get; set; }","sourceCodeStart":474,"sourceCodeEnd":510,"githubUrl":"https://github.com/babalae/better-genshin-impact/blob/a7cb36712dcb409be610257d877fcea3597e9d6b/BetterGenshinImpact/Core/BgiVision/BvFlow.cs#L474-L510","documentation":"Thrown by ReadLimitedAsync when the cumulative bytes read from a stream exceed MaxDownloadBytes (20 MB) during incremental copy. Unlike the Content-Length pre-check, this guards against chunked-transfer responses or servers that underreport Content-Length — it monitors the actual byte count as data arrives.","triggerScenarios":"ReadLimitedAsync loops reading into an 81920-byte buffer; when output.Length + read exceeds MaxDownloadBytes it throws. Triggered by HTTP responses without Content-Length (Transfer-Encoding: chunked) where the actual body exceeds 20 MB, or by pack resource streams larger than the limit.","commonSituations":"Server uses chunked encoding and streams a large image, Content-Length was absent so the pre-check didn't fire, or a pack resource stream is unexpectedly large.","solutions":["Use a smaller image source or compress the image.","If legitimate, increase MaxDownloadBytes (recompile required).","Verify the server isn't streaming additional content (e.g. HTML error page) that inflates the body."],"exampleFix":"// before\nif (output.Length + read > MaxDownloadBytes)\n    throw new InvalidDataException($\"图片大小超过 {MaxDownloadBytes / 1024 / 1024} MB 限制。\");\n\n// after — stop reading early and return partial/placeholder\nif (output.Length + read > MaxDownloadBytes)\n{\n    _owner.ReportDiagnostic(new MarkdownDiagnostic(MarkdownDiagnosticSeverity.Warning,\n        \"流式读取时图片大小超过限制，已跳过。\"));\n    return Array.Empty<byte>(); // caller handles empty as placeholder\n}","handlingStrategy":"try-catch","validationCode":"// Content-Length pre-check helps, but chunked streams need the runtime guard\n// No additional pre-validation possible for chunked streams","typeGuard":null,"tryCatchPattern":"try { bytes = await ReadLimitedAsync(responseStream, ct); }\ncatch (InvalidDataException ex) when (ex.Message.Contains(\"MB 限制\"))\n{ return MarkdownImageResult.Placeholder; }","preventionTips":["Always use ResponseHeadersRead + ReadLimitedAsync for untrusted HTTP sources.","Monitor actual vs declared sizes to detect server misreporting.","Dispose the HTTP response promptly when the limit is exceeded."],"tags":["markdown","image","stream","size-limit","network"],"backgroundTag":null,"analyzedSha":"a7cb36712dcb409be610257d877fcea3597e9d6b","analyzedAt":"2026-08-13T16:44:57.548Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}