More than one macro confuses Julia. What I have ended up doing is getting rid of one macro call and burying the other one.
Something like
function title_string(current_iter, current_J)
@sprintf "iteration : %.0f\ncost function : %.3e" current_iter current_J
end
iter_idx = Observable(1)
text_itr = lift(t -> title_string(trace_J[t], t - 1), iter_idx) #Avoid the macro call here
text!(ax1, Point2f(0, 0), text=text_str, align=(:left, :top))
(You may need to adjust to make it run but that is the idea)