That’s because ConsoleLogger is doing additional formatting of the backtrace to print it. You can do that manually by logging exception = sprint(Base.display_error, e, catch_backtrace()) instead of the tuple.
But if you want JSON in the end, probably the easiest way to do that is to use LoggingFormats.jl:
julia> with_logger(FormatLogger(LoggingFormats.JSON(), stderr)) do
try
sqrt(-1)
catch e
@error "My task errored!" exception=(e, catch_backtrace())
end
end
{"level":"error","msg":"My task errored!","module":"Main","file":"REPL[8]","line":5,"group":"REPL[8]","id":"Main_ff590be1","kwargs":{"exception":"ERROR: DomainError with -1.0:\nsqrt was called with a negative real argument but will only return a complex result if called with a complex argument. Try sqrt(Complex(x)).\nStacktrace:\n [1] throw_complex_domainerror(f::Symbol, x::Float64)\n @ Base.Math ./math.jl:33\n [2] sqrt\n @ ./math.jl:686 [inlined]\n [3] sqrt(x::Int64)\n @ Base.Math ./math.jl:1578\n [4] (::var\"#9#10\")()\n @ Main ./REPL[8]:3\n [5] with_logstate(f::Function, logstate::Any)\n @ Base.CoreLogging ./logging.jl:515\n [6] with_logger(f::Function, logger::FormatLogger)\n @ Base.CoreLogging ./logging.jl:627\n [7] top-level scope\n @ REPL[8]:1\n [8] eval\n @ ./boot.jl:385 [inlined]\n [9] eval_user_input(ast::Any, backend::REPL.REPLBackend, mod::Module)\n @ REPL ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/REPL/src/REPL.jl:150\n [10] repl_backend_loop(backend::REPL.REPLBackend, get_module::Function)\n @ REPL ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/REPL/src/REPL.jl:246\n [11] start_repl_backend(backend::REPL.REPLBackend, consumer::Any; get_module::Function)\n @ REPL ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/REPL/src/REPL.jl:231\n [12] run_repl(repl::REPL.AbstractREPL, consumer::Any; backend_on_current_task::Bool, backend::Any)\n @ REPL ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/REPL/src/REPL.jl:389\n [13] run_repl(repl::REPL.AbstractREPL, consumer::Any)\n @ REPL ~/.julia/juliaup/julia-1.10.3+0.aarch64.apple.darwin14/share/julia/stdlib/v1.10/REPL/src/REPL.jl:375\n [14] (::Base.var\"#1013#1015\"{Bool, Bool, Bool})(REPL::Module)\n @ Base ./client.jl:432\n [15] #invokelatest#2\n @ ./essentials.jl:892 [inlined]\n [16] invokelatest\n @ ./essentials.jl:889 [inlined]\n [17] run_main_repl(interactive::Bool, quiet::Bool, banner::Bool, history_file::Bool, color_set::Bool)\n @ Base ./client.jl:416\n [18] exec_options(opts::Base.JLOptions)\n @ Base ./client.jl:333\n [19] _start()\n @ Base ./client.jl:552\n"}}
Note the backtrace is formatted automatically, since there is handling for that.