Terminate after warning is thrown - global setting

I want to ensure that my program runs without doing questionable operations. Thus I would like the program to terminate whenever a warning is thrown; i.e. promote a warning to the level of errors.

Is there a way to do this? I have the Python equivalent warnings.filterwarnings("error") of the warnings package in mind.

1 Like

Julia doesn’t “throw” warnings. However, warning messages are typically written to the stderr stream, so you can turn such warnings to errors simply by redirecting stderr to a read-only stream:

julia> redirect_stderr(open(touch(tempname()), "r"))
IOStream(<file ...>)

julia> @warn "foo"
ERROR: ArgumentError: write failed, IOStream is not writeable

(With a bit more work, I guess you could change stderr to a pipeline of some sort that captures the warning message and re-prints it.)

1 Like

You can install a custom logger that eg. terminates the process for messages with level higher than warnings:

julia> using Logging, LoggingExtras

julia> terminator = EarlyFilteredLogger(global_logger()) do log_args
           if log_args.level >= Logging.Warn
               println(stderr, "ERROR: Log message with higher level than Logging.Warn, terminating process.")
               exit(-1)
           end
           return true
       end;

julia> global_logger(terminator);

julia> @info "hello"
[ Info: hello

julia> @warn "world"
ERROR: Log message with higher level than Logging.Warn, terminating process.

$ # back to shell prompt
4 Likes

I suppose there is a way to add a trace back to this fine solution ?
regards,

If you just want to promote the level from warning to error you can do that with a custom logger too, but as Steven said, error log messages don’t terminate the process (@error "something" is not the same as error("something")):

julia> using LoggingExtras, Logging

julia> promoter = TransformerLogger(global_logger()) do log_args
           if Logging.Error > log_args.level >= Logging.Warn
               return merge(log_args, (; level = Logging.Error))
           else
               return log_args
           end
       end;

julia> global_logger(promoter);

julia> @info "hello"
[ Info: hello

julia> @warn "warn"
┌ Error: warn
└ @ Main REPL[11]:1
1 Like

Like all errors it should render a stacktrace if uncaught.
But if you are just raising it to @error level you can put in the stacktrace in the transformer logger manually.
like is shown in:

If I understand this thread, it seems to offer options for forcing a traceback at some suspected code location(s), where the trigger can be installed.
But if (thousands of) warning messages start to appear from a package function that is used in many places in both new and legacy code, we need a method to identify those locations.
(Such a flood of new warnings might be precipitated by, e.g., updating julia or the manifest, or changes in the nature of source data.)
One solution might be some global control for each package to force a traceback from any warning from that package. Some packages like NonlinearSolve offer [Tracing Controls], (Common Solver Options (Solve Keyword Arguments) · NonlinearSolve.jl) but those need to be controlled separately at each Problem definition, which is impractical for the situation I described. The suggestion to redirect the stderr stream to a write-only file would seem to block the traceback.
Or am I missing something?
thnaks