You actually don’t need the asException identity function as your variants don’t have a payload and are thus coercible to strings. But it might be more convenient still.
type functionsErrorCode =
| @as("ok") Ok
| @as("cancelled") Cancelled
let error = (Cancelled :> string)->Error.make