diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
index 67267ff2581..aaccaaba9ea 100644
--- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
+++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
@@ -1,12 +1,12 @@
### Fixed
+* Preserve source range for type errors on empty-bodied computation expressions (e.g. `foo {}`) in pipelines, function arguments, and type-annotated contexts, instead of reporting `unknown(1,1)`. ([Issue #19550](https://github.com/dotnet/fsharp/issues/19550), [PR #19849](https://github.com/dotnet/fsharp/pull/19849))
* Tooltip "Full name" now shows demangled companion module names (e.g. `MyType.func` instead of `MyTypeModule.func`). ([Issue #17335](https://github.com/dotnet/fsharp/issues/17335), [PR #19867](https://github.com/dotnet/fsharp/pull/19867))
* Fix internal error (FS0193) when calling an indexed property setter with a named argument that matches an indexer parameter. ([Issue #16034](https://github.com/dotnet/fsharp/issues/16034), [PR #19851](https://github.com/dotnet/fsharp/pull/19851))
* Fix missing FS1182 ("unused binding") warning for unused `let` function bindings inside class types. ([Issue #13849](https://github.com/dotnet/fsharp/issues/13849), [PR #19805](https://github.com/dotnet/fsharp/pull/19805))
* Fix inner mutually-recursive `let rec ... and ...` functions under `--realsig+` not being lifted to top-level static methods (TLR), causing `FSharpFunc` closure allocations and loss of `tail.` opcodes — the large struct-mutual-recursion perf regression reported in [Issue #17607](https://github.com/dotnet/fsharp/issues/17607). ([PR #19882](https://github.com/dotnet/fsharp/pull/19882))
* Fix `TypeLoadException` ("Specialize tried to implicitly override a method with weaker type parameter constraints") and the related CLR crash with constrained inline calls by stripping constraints from closure-class typars in `EraseClosures.convIlxClosureDef`. ([Issue #14492](https://github.com/dotnet/fsharp/issues/14492), [Issue #19075](https://github.com/dotnet/fsharp/issues/19075), [PR #19882](https://github.com/dotnet/fsharp/pull/19882))
* Fix `FieldAccessException` at runtime when the optimizer relocates a read of a `protected` (family) base-class field into a method outside the field's family (e.g. a trivial member inlined into module/startup code under `--optimize+`). Protected (family) IL field access is no longer hoisted out of its declaring family by inlining or method-splitting. ([Issue #19963](https://github.com/dotnet/fsharp/issues/19963), [PR #19964](https://github.com/dotnet/fsharp/pull/19964))
-
* Suppress hover/symbol resolution for wildcard `_` patterns inside `member _.…` bodies that incorrectly showed `val _: T` tooltip. ([PR #19760](https://github.com/dotnet/fsharp/pull/19760))
* Deduplicate format specifier locations in computation expressions so editor tooling no longer reports duplicate entries for the same `%` specifier. ([Issue #16419](https://github.com/dotnet/fsharp/issues/16419), [PR #19791](https://github.com/dotnet/fsharp/pull/19791))
* Reject non-function bindings for single-case and partial active pattern names with FS1209, matching the existing multi-case behavior. ([PR #19763](https://github.com/dotnet/fsharp/pull/19763))
diff --git a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
index b05df442d36..2e258b1b2c9 100644
--- a/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
+++ b/src/Compiler/Checking/Expressions/CheckComputationExpressions.fs
@@ -1610,7 +1610,8 @@ let rec TryTranslateComputationExpression
error (Error(FSComp.SR.tcEmptyBodyRequiresBuilderZeroMethod (), ceenv.mWhole))
| _ -> error (Error(FSComp.SR.tcRequireBuilderMethod "Zero", m))
- Some(translatedCtxt (mkSynCall "Zero" m [] ceenv.builderValName))
+ let mCall = if equals m range0 then ceenv.mWhole else m
+ Some(translatedCtxt (mkSynCall "Zero" mCall [] ceenv.builderValName))
| OptionalSequential(JoinOrGroupJoinOrZipClause ceenv (_, _, _, _, _, mClause), _) when firstTry = CompExprTranslationPass.Initial ->
diff --git a/src/Compiler/Checking/Expressions/CheckExpressions.fs b/src/Compiler/Checking/Expressions/CheckExpressions.fs
index 070ce6b3e8e..dfd00c69880 100644
--- a/src/Compiler/Checking/Expressions/CheckExpressions.fs
+++ b/src/Compiler/Checking/Expressions/CheckExpressions.fs
@@ -8884,7 +8884,7 @@ and TcApplicationThen (cenv: cenv) (overallTy: OverallTy) env tpenv mExprAndArg
// leftExpr { }
| SynExpr.ComputationExpr (false, comp, _m)
| SynExpr.Record (None, None, EmptyFieldListAsUnit comp, _m) ->
- let bodyOfCompExpr, tpenv = cenv.TcComputationExpression cenv env overallTy tpenv (mLeftExpr, leftExpr.Expr, exprTy, comp)
+ let bodyOfCompExpr, tpenv = cenv.TcComputationExpression cenv env overallTy tpenv (mExprAndArg, leftExpr.Expr, exprTy, comp)
TcDelayed cenv overallTy env tpenv mExprAndArg (MakeApplicableExprNoFlex cenv bodyOfCompExpr) (tyOfExpr g bodyOfCompExpr) ExprAtomicFlag.NonAtomic delayed
| _ ->
diff --git a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
index 3fc031a525f..c109944620f 100644
--- a/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
+++ b/tests/FSharp.Compiler.ComponentTests/FSharp.Compiler.ComponentTests.fsproj
@@ -355,6 +355,7 @@
+
diff --git a/tests/FSharp.Compiler.ComponentTests/Language/CE_PipelineRange19550.fs b/tests/FSharp.Compiler.ComponentTests/Language/CE_PipelineRange19550.fs
new file mode 100644
index 00000000000..619fcfa179a
--- /dev/null
+++ b/tests/FSharp.Compiler.ComponentTests/Language/CE_PipelineRange19550.fs
@@ -0,0 +1,278 @@
+// Copyright (c) Microsoft Corporation. All Rights Reserved. See License.txt in the project root for license information.
+
+namespace Language
+
+open Xunit
+open FSharp.Test.Compiler
+
+// https://github.com/dotnet/fsharp/issues/19550
+module CE_PipelineRange19550 =
+
+ let private errorsOf (result: CompilationResult) : ErrorInfo list =
+ let diags =
+ match result with
+ | CompilationResult.Success r
+ | CompilationResult.Failure r -> r.Diagnostics
+ diags
+ |> List.filter (fun d ->
+ match d.Error with ErrorType.Error _ -> true | _ -> false)
+
+ let private dump (result: CompilationResult) : string =
+ errorsOf result
+ |> List.map (fun d ->
+ let n =
+ match d.Error with
+ | ErrorType.Error n
+ | ErrorType.Warning n
+ | ErrorType.Information n
+ | ErrorType.Hidden n -> n
+ sprintf " FS%04d (L%d,C%d)-(L%d,C%d): %s"
+ n d.Range.StartLine (d.Range.StartColumn + 1)
+ d.Range.EndLine (d.Range.EndColumn + 1) d.Message)
+ |> String.concat "\n"
+
+ let private hasDiagAt (code: int) (sLine, sCol, eLine, eCol) (result: CompilationResult) : CompilationResult =
+ let found =
+ errorsOf result
+ |> List.exists (fun d ->
+ (match d.Error with ErrorType.Error c -> c = code | _ -> false)
+ && d.Range.StartLine = sLine
+ && d.Range.StartColumn + 1 = sCol
+ && d.Range.EndLine = eLine
+ && d.Range.EndColumn + 1 = eCol)
+ if not found then
+ failwithf
+ "Expected diagnostic FS%04d at (Line %d, Col %d)-(Line %d, Col %d). Actual diagnostics:\n%s"
+ code sLine sCol eLine eCol (dump result)
+ result
+
+ let private hasNoRange0Error (result: CompilationResult) : CompilationResult =
+ let bad =
+ errorsOf result
+ |> List.filter (fun d ->
+ d.Range.StartLine = 1 && d.Range.StartColumn = 0
+ && d.Range.EndLine = 1 && d.Range.EndColumn = 0)
+ if not (List.isEmpty bad) then
+ failwithf
+ "Unexpected range0 / unknown(1,1) error diagnostic. All diagnostics:\n%s"
+ (dump result)
+ result
+
+ []
+ let ``Issue 19550 - empty CE body in pipeline reports source range``() =
+ FSharp """
+module Repro19550_01
+type FooBuilder() =
+ member _.Zero() = fun x -> x + 42
+
+let foo = FooBuilder()
+
+"" |> foo {} |> printfn "%d"
+ """
+ |> compile
+ |> shouldFail
+ |> hasDiagAt 193 (8, 7, 8, 13)
+
+ []
+ let ``Issue 19550 - single pipe with empty CE body has non-zero range``() =
+ FSharp """
+module Repro19550_02
+type FooBuilder() =
+ member _.Zero() = fun x -> x + 42
+
+let foo = FooBuilder()
+
+foo {} |> printfn "%d"
+ """
+ |> compile
+ |> shouldFail
+ |> hasNoRange0Error
+
+ []
+ let ``Issue 19550 - empty CE body as function argument``() =
+ FSharp """
+module Repro19550_03
+type FooBuilder() =
+ member _.Zero() = fun x -> x + 42
+
+let foo = FooBuilder()
+
+let take (x: int) = x
+let _ = take (foo {})
+ """
+ |> compile
+ |> shouldFail
+ |> hasDiagAt 193 (9, 15, 9, 21)
+
+ []
+ let ``Issue 19550 - explicit type annotation mismatch on empty CE body``() =
+ FSharp """
+module Repro19550_04
+type FooBuilder() =
+ member _.Zero() = fun x -> x + 42
+
+let foo = FooBuilder()
+
+let x : int = foo {}
+ """
+ |> compile
+ |> shouldFail
+ |> hasDiagAt 193 (8, 15, 8, 21)
+
+ []
+ let ``Issue 19550 - Yield builder in pipeline keeps non-zero range``() =
+ FSharp """
+module Repro19550_05a
+type YBuilder() =
+ member _.Yield(x) = fun y -> x + y
+
+let yb = YBuilder()
+
+"" |> yb { yield 1 } |> printfn "%d"
+ """
+ |> compile
+ |> shouldFail
+ |> hasNoRange0Error
+
+ []
+ let ``Issue 19550 - Return builder in pipeline keeps non-zero range``() =
+ FSharp """
+module Repro19550_05b
+type RBuilder() =
+ member _.Return(x) = fun y -> x + y
+
+let rb = RBuilder()
+
+"" |> rb { return 1 } |> printfn "%d"
+ """
+ |> compile
+ |> shouldFail
+ |> hasNoRange0Error
+
+ []
+ let ``Issue 19550 - Bind builder in pipeline keeps non-zero range``() =
+ FSharp """
+module Repro19550_05c
+type BBuilder() =
+ member _.Bind(x, f) = f x
+ member _.Return(x) = fun y -> x + y
+
+let bb = BBuilder()
+
+"" |> bb { let! x = 1 in return x } |> printfn "%d"
+ """
+ |> compile
+ |> shouldFail
+ |> hasNoRange0Error
+
+ []
+ let ``Issue 19550 - nested CE - inner empty body in pipeline``() =
+ FSharp """
+module Repro19550_06
+type FooBuilder() =
+ member _.Zero() = fun x -> x + 42
+
+let foo = FooBuilder()
+
+type Outer() =
+ member _.Yield(_) : unit = ()
+ member _.Combine(_, _) = ()
+ member _.Delay(f: unit -> unit) = f ()
+ member _.Zero() = ()
+
+let outer = Outer()
+
+let _ = outer { do "" |> foo {} |> ignore }
+ """
+ |> compile
+ |> shouldFail
+ |> hasDiagAt 193 (16, 26, 16, 32)
+
+ []
+ let ``Issue 19550 - valid empty CE body without type mismatch still compiles``() =
+ FSharp """
+module Repro19550_07
+type IdBuilder() =
+ member _.Zero() = 0
+
+let id1 = IdBuilder()
+let v : int = id1 {}
+ """
+ |> compile
+ |> shouldSucceed
+ |> ignore
+
+ []
+ let ``Issue 19550 - non-pipeline empty CE body reports source range``() =
+ FSharp """
+module Repro19550_08
+type FooBuilder() =
+ member _.Zero() = fun x -> x + 42
+
+let foo = FooBuilder()
+
+let f : string -> string = foo {}
+ """
+ |> compile
+ |> shouldFail
+ |> hasDiagAt 193 (8, 28, 8, 34)
+
+ []
+ let ``Issue 19550 - non-CE pipeline mismatch keeps non-zero range``() =
+ FSharp """
+module Repro19550_09
+let _ = "" |> (fun (x: int) -> x) |> printfn "%d"
+ """
+ |> compile
+ |> shouldFail
+ |> hasNoRange0Error
+
+ []
+ let ``Issue 19550 - multi-line empty CE body in pipeline``() =
+ FSharp """
+module Repro19550_10
+type FooBuilder() =
+ member _.Zero() = fun x -> x + 42
+
+let foo = FooBuilder()
+
+"" |>
+ foo {
+ } |>
+ printfn "%d"
+ """
+ |> compile
+ |> shouldFail
+ |> hasDiagAt 193 (9, 4, 10, 5)
+
+ []
+ let ``Issue 19550 - empty CE body in match arm pipeline``() =
+ FSharp """
+module Repro19550_11
+type FooBuilder() =
+ member _.Zero() = fun x -> x + 42
+
+let foo = FooBuilder()
+
+let r = match 0 with
+ | _ -> "" |> foo {} |> printfn "%d"
+ """
+ |> compile
+ |> shouldFail
+ |> hasDiagAt 193 (9, 22, 9, 28)
+
+ []
+ let ``Issue 19550 - both Zero and Yield - empty body picks Zero path``() =
+ FSharp """
+module Repro19550_12
+type BothBuilder() =
+ member _.Zero() = fun x -> x + 1
+ member _.Yield(x) = fun y -> x + y
+
+let bb = BothBuilder()
+
+"" |> bb {} |> printfn "%d"
+ """
+ |> compile
+ |> shouldFail
+ |> hasDiagAt 193 (9, 7, 9, 12)