Strange Makie Observable updating behavior within recipe

Hello all, I’m currently facing a strange error while using a custom recipe. This error only showed up with recent versions of Makie, but I could not find the source.

Here is the problem, for meshscatters, Makie has only the :Sphere option available, so I figured I could define my own addition and define several 3D marker shapes to pass to meshscatter. However, I’d like to keep the capability to update this marker shape on the fly with an Observable. This gives the following code

using GLMakie

function marker_geometry(marker_symbol::Symbol, marker_size::Real)
    marker_size = Float64(marker_size)
    if marker_symbol === :sphere
        return Makie.Sphere(Makie.Point3(0.0), marker_size)
    elseif marker_symbol === :cube
        return Makie.Rect3(Makie.Vec3(-marker_size), Makie.Vec3(2 * marker_size))
    elseif marker_symbol === :pyramid
        return Makie.Pyramid(Makie.Point3(0.0, 0.0, marker_size / 2), marker_size, marker_size)
    elseif marker_symbol === :cylinder
        return Makie.Cylinder(Makie.Point3(0.0, 0.0, -marker_size), Makie.Point3(0.0, 0.0, marker_size), marker_size)
        @warn "nodemarker must be either set to (:sphere, :cube, :pyramid, :cylinder), defaulting to :sphere"
        return Makie.Sphere(Makie.Point3(0.0), marker_size)

Makie.@recipe(NodePlot, points) do scene

function Makie.plot!(plt::NodePlot{<:Tuple{Any}})
    # Unpack all relevant arguments
    (; points, nodemarker, nodesize) = plt
    # Actually draw the markers
    marker = Observable{Any}()
    lift(nodemarker, nodesize) do nodemarker, nodesize
        # Define the marker object depending on the selected option
        marker[] = marker_geometry(nodemarker, nodesize)
    meshscatter!(plt, points, marker=marker)
    return plt

If I try and plot this with

f,ax,p = nodeplot(rand(Point3,10))
p.nodemarker = :cube

I get the following error

ERROR: MethodError: Cannot `convert` an object of type Rect3{Float64} to an object of type Sphere{Float64}

Closest candidates are:
  convert(::Type{T}, ::T) where T
   @ Base Base.jl:84
  (::Type{GeometryBasics.HyperSphere{N, T}} where {N, T})(::Any, ::Any)

so it looks like there is another observable in the background that is concretely typed and blocks me from updating the marker. The weird part is that Makie actually shows cubes regardless. Also directly passing a 3D shape to meshscatter works fine, so it looks like it’s really in the recipe.

Can someone explain this behavior ?

EDIT Here is the stacktrace

  [1] setproperty!(x::Observable{Sphere{Float64}}, f::Symbol, v::Rect3{Float64})
    @ Base .\Base.jl:40
  [2] setindex!(observable::Observable, val::Any)
    @ Observables user\.julia\packages\Observables\YdEbO\src\Observables.jl:122
  [3] (::Observables.MapCallback)(value::Any)
    @ Observables user\.julia\packages\Observables\YdEbO\src\Observables.jl:436
  [4] #invokelatest#2
    @ Base .\essentials.jl:887 [inlined]
  [5] invokelatest
    @ Base .\essentials.jl:884 [inlined]
  [6] notify
    @ Observables user\.julia\packages\Observables\YdEbO\src\Observables.jl:206 [inlined]
  [7] setindex!(observable::Observable, val::Any)
    @ Observables user\.julia\packages\Observables\YdEbO\src\Observables.jl:123
  [8] setindex!(x::Plot{nodeplot, Tuple{Vector{Point3}}}, value::Symbol, key::Symbol)
    @ MakieCore user\.julia\packages\MakieCore\UAwps\src\attributes.jl:224
  [9] setproperty!(x::Plot{nodeplot, Tuple{Vector{Point3}}}, key::Symbol, value::Symbol)
    @ MakieCore user\.julia\packages\MakieCore\UAwps\src\attributes.jl:101

does the stacktrace point to the place where the conversion fails?

I just added the stacktrace.

Ah I think I got it, the observable that’s erroring is the one you create with lift but don’t store. It’s strongly typed the first time you run it. Use onany(...; update = true) to get similar behavior without making an observable.

Yes ! That worked ! Thanks ! I’m just wondering if recent changes in Makie led to that problem, because the code with lift was working until recently.