Makie Axis xticks: passing (datetimes, labels) fails with MethodError

Hello!

I’m trying to change the DateTime xtick label intervals in my Makie plot by manually passing the xticks parameter to Axis as a tuple with two vectors: (datetimes, labels). According to the current xticks docs:

The following is a list of common tick objects.

Numeric:

  • A vector of numbers
  • (…)

DateTime:

  • A vector of DateTimes
  • A tuple with two vectors (datetimes, labels)
  • DateTimeTicks, the default tick finder for datetime ticks

However, with this MWE

using CairoMakie
fig = Figure()
x = DateTime(2025, 1, 1):Day(1):DateTime(2025, 1, 10) 
ax = Axis(fig[1, 1], xticks=(x, string.(x)))
lines!(ax, x, rand(10))

I get:

MethodError: Cannot `convert` an object of type DateTime to an object of type Float64
The function `convert` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  convert(::Type{T}, ::IntervalArithmetic.ExactReal) where T<:Real
   @ IntervalArithmetic ~/.julia/packages/IntervalArithmetic/55mUT/src/intervals/exact_literals.jl:130
  convert(::Type{T}, ::Unitful.Quantity) where T<:Real
   @ Unitful ~/.julia/packages/Unitful/pKTDo/src/conversion.jl:167
  convert(::Type{T}, ::Unitful.Level) where T<:Real
   @ Unitful ~/.julia/packages/Unitful/pKTDo/src/logarithm.jl:46
  ...

Any idea of what I am missing here?

Thanks in advance!


Environment Packages
  [13f3f980] CairoMakie v0.15.8
  [a93c6f00] DataFrames v1.8.1
  [7073ff75] IJulia v1.33.0
  [945b72a4] MarketData v0.15.1
Full Stacktrace
MethodError: Cannot `convert` an object of type Date to an object of type Float64
The function `convert` exists, but no method is defined for this combination of argument types.

Closest candidates are:
  convert(::Type{T}, ::IntervalArithmetic.ExactReal) where T<:Real
   @ IntervalArithmetic ~/.julia/packages/IntervalArithmetic/55mUT/src/intervals/exact_literals.jl:130
  convert(::Type{T}, ::Unitful.Quantity) where T<:Real
   @ Unitful ~/.julia/packages/Unitful/pKTDo/src/conversion.jl:167
  convert(::Type{T}, ::Unitful.Level) where T<:Real
   @ Unitful ~/.julia/packages/Unitful/pKTDo/src/logarithm.jl:46
  ...


Stacktrace:
  [1] setindex!
    @ ./genericmemory.jl:259 [inlined]
  [2] unsafe_copyto!(dest::Memory{Float64}, doffs::Int64, src::Memory{Date}, soffs::Int64, n::Int64)
    @ Base ./genericmemory.jl:158
  [3] unsafe_copyto!
    @ ./genericmemory.jl:137 [inlined]
  [4] _copyto_impl!
    @ ./array.jl:308 [inlined]
  [5] copyto!
    @ ./array.jl:294 [inlined]
  [6] copyto!
    @ ./array.jl:319 [inlined]
  [7] copyto_axcheck!
    @ ./abstractarray.jl:1176 [inlined]
  [8] Array
    @ ./array.jl:621 [inlined]
  [9] convert
    @ ./array.jl:614 [inlined]
 [10] get_tickvalues
    @ ~/.julia/packages/Makie/Vn16E/src/makielayout/lineaxis.jl:678 [inlined]
 [11] get_tickvalues
    @ ~/.julia/packages/Makie/Vn16E/src/makielayout/lineaxis.jl:610 [inlined]
 [12] get_ticks
    @ ~/.julia/packages/Makie/Vn16E/src/makielayout/lineaxis.jl:598 [inlined]
 [13] get_ticks(::Nothing, ticks::Vector{Date}, scale::Function, formatter::Makie.Automatic, vmin::Float64, vmax::Float64)
    @ Makie ~/.julia/packages/Makie/Vn16E/src/dim-converts/dim-converts.jl:77
 [14] (::Makie.var"#LineAxis##22#LineAxis##23"{Observable{Any}})(::Tuple{Float32, Tuple{Float32, Float32}, Bool}, ::Nothing, limits::Tuple{Float64, Float64}, ticks::Vector{Date}, tickformat::Makie.Automatic, scale::Function)
    @ Makie ~/.julia/packages/Makie/Vn16E/src/makielayout/lineaxis.jl:449
 [15] (::Observables.MapCallback)(value::Any)
    @ Observables ~/.julia/packages/Observables/YdEbO/src/Observables.jl:436
 [16] #map!#298
    @ ~/.julia/packages/Makie/Vn16E/src/scenes.jl:191 [inlined]
 [17] map!
    @ ~/.julia/packages/Makie/Vn16E/src/scenes.jl:181 [inlined]
 [18] Makie.LineAxis(parent::Scene, attrs::Attributes)
    @ Makie ~/.julia/packages/Makie/Vn16E/src/makielayout/lineaxis.jl:445
 [19] Makie.LineAxis(parent::Scene; kwargs...)
    @ Makie ~/.julia/packages/Makie/Vn16E/src/makielayout/lineaxis.jl:8
 [20] LineAxis
    @ ~/.julia/packages/Makie/Vn16E/src/makielayout/lineaxis.jl:6 [inlined]
 [21] initialize_block!(ax::Axis; palette::Nothing)
    @ Makie ~/.julia/packages/Makie/Vn16E/src/makielayout/blocks/axis.jl:346
 [22] initialize_block!(ax::Axis)
    @ Makie ~/.julia/packages/Makie/Vn16E/src/makielayout/blocks/axis.jl:154
 [23] _block(T::Type{Axis}, fig_or_scene::Figure, args::Vector{Any}, kwdict::Dict{Symbol, Any}, bbox::Nothing; kwdict_complete::Bool)
    @ Makie ~/.julia/packages/Makie/Vn16E/src/makielayout/blocks.jl:405
 [24] _block
    @ ~/.julia/packages/Makie/Vn16E/src/makielayout/blocks.jl:321 [inlined]
 [25] #_block#1538
    @ ~/.julia/packages/Makie/Vn16E/src/makielayout/blocks.jl:266 [inlined]
 [26] _block(::Type{Axis}, ::GridPosition; kwargs::@Kwargs{xticks::Vector{Date}, yticks::UnitRange{Int64}, ylabel::String})
    @ Makie ~/.julia/packages/Makie/Vn16E/src/makielayout/blocks.jl:260
 [27] _block
    @ ~/.julia/packages/Makie/Vn16E/src/makielayout/blocks.jl:251 [inlined]
 [28] #_#1536
    @ ~/.julia/packages/Makie/Vn16E/src/makielayout/blocks.jl:242 [inlined]
 [29] top-level scope
    @ In[39]:8
 [30] eval(m::Module, e::Any)

Yeah, the problem is that Makie tries to use the float axis tick logic on your tick object, because at this point it doesn’t yet know you’re trying to use a datetime axis. You could plot the lines first (then the Axis has changed to datetime mode) and then set the ticks.