Skip to content

Better err msg - #1201

Open
riclarsson wants to merge 2 commits into
atmtools:mainfrom
riclarsson:better-err-msg
Open

riclarsson wants to merge 2 commits into
atmtools:mainfrom
riclarsson:better-err-msg

Conversation

@riclarsson

Copy link
Copy Markdown
Contributor

AI PR message:

Summary

Error messages are shorter and easier to read, and ARTS_USER_ERROR / ARTS_USER_ERROR_IF are replaced by a plain function, arts::user_error.

Most of the 215 changed files are the mechanical macro conversion. The substantive changes are in debug.h/debug.cpp, mystring.h/mystring.cpp, workspace_method_class.cpp, gen_auto_py_methods.cpp, species_tags.cc and the files listed under "Message fixes".

Error layout

  • ARTS_METHOD_ERROR_CATCH indents the error it passes on by two spaces, so nested functions give a readable trace instead of one flat block.
  • Python method errors no longer print "Method reports the following error(s):"; the error is indented under the method call instead.
  • Errors from methods in agendas list their inputs and outputs without the internal _/@ prefixes, and the line explaining those prefixes is gone. Inputs and outputs were printed swapped; that is fixed.
  • Release builds show user errors as the message only; function names come from ARTS_METHOD_ERROR_CATCH. Debug and RelWithDebInfo builds still add file, function, line and column. The Fail check: <condition> line is gone in all builds.
  • New indent(text, indentation = " ") in mystring.h. mystring.h/mystring.cpp move from the strings library to util, so debug.cpp can use it.

Example, an IGRF time outside the valid range, Release build. Before:

Cannot execute method:

  atm_fieldSchmidthFieldFromIGRF(atm_field : self.atm_field,
                                 time      : User-provided Time)

Method reports the following error(s):
Fail check: year < valid_range.first or year > valid_range.second

User error found in:

Filename:      .../src/core/igrf/igrf.cpp
Function Name: std::pair<Coefficients, Coefficients> IGRF::coefficients(const Time &)
Line Number:   40
Column Number: 11


Please follow these instructions to correct the error:

The IGRF coefficients are valid from the decimal year 1900 to 2030, but the time 1850-01-01 00:00:00.000000+00:00 is the decimal year 1850

After:

Cannot execute method:

  atm_fieldSchmidthFieldFromIGRF(atm_field : self.atm_field,
                                 time      : User-provided Time)

    The IGRF coefficients are valid from the decimal year 1900 to 2030, but the time 1850-01-01 00:00:00.000000+00:00 is the decimal year 1850

arts::user_error replaces the macros

arts::user_error("x has {} elements but y has {}", x.size(), y.size());

if (x.size() != y.size()) arts::user_error("x has {} elements but y has {}", x.size(), y.size());
  • [[noreturn]], so it can end a function or a switch default.
  • Checks are written as an if around the call. The arguments are only evaluated when the check fails, exactly as with the old macro; a passing check costs nothing beyond its condition, in every build type.
  • The call location is captured by the format string's consteval constructor (std::source_location as a default argument). No macros, standard C++23.
  • Checked at compile time: the format string must use every argument (std::format itself accepts unused ones), and every argument must be formattable. A violation is a compile error at the call.
  • A message without arguments is used as it is, without formatting.
  • 1,692 call sites converted with a script: 122 ARTS_USER_ERROR, 1,570 ARTS_USER_ERROR_IF.

Message fixes

  • No more "Internal error" for user mistakes: unknown species, isotopologues and CIA partners in species tags now name the bad part, list the valid choices and point to arts-cat-data; HITRAN/JPL record parsing, surface normals and Python callbacks are reworded.
  • The two Wigner initialization checks said "Must not be initialized." when the library was not initialized.
  • Short messages now give the values involved: sensor element setters, path grids, polarization, DISORT subsurface sizes, surface extrapolation, gridded-field shape mismatches (was "bad field"), MT_CKD data, line-shape temperature models, Jacobian x-vector checks.
  • Eight messages silently dropped their arguments (iostream-style "text", x, "more", or a missing {}); found by the new compile-time check: atm_field.cpp, xml_io_old.cc (2), lbl_hitran.cpp, rtepack_transmission.cc, test_mdspan.cc (3).

Other fixes

  • extract1D read past the end of single-point grids (x.size() > 0 should be > 1).

Notes

  • Debug builds no longer show the text of the failing condition; file and line point to it.
  • doc/arts/dev.error.rst is rewritten for arts::user_error.
  • Tested with Clang on macOS: builds without new warnings and passes the full test suite. Not tested with MSVC.

🤖 Generated with Claude Code

@olemke

olemke commented Oct 23, 2026

Copy link
Copy Markdown
Member

I like that the error macros are now plain functions.

I don't like that the location of the error (filename, function, line number) is now only available in debug/relwithdebinfo builds. Knowing the exact place where the error occurred without having to re-run the whole setup in a debug/relwithdebinfo build to get that information was very helpful. Especially if you try to diagnose error reports from end-users.

@riclarsson

Copy link
Copy Markdown
Contributor Author

I agree it is useful. But the error messages looks more like C++ stacktraces than useful help to ensure people can fix what is wrong. That is not a good way to represent what is happening for python users.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants