Project 1 - Improve error messages, reduce need for explanations in documentation
Overview and Motivation
Old approach
Traditionally, error messages in LAMMPS would be rather terse and often
very generic (Example: Illegal pair command
) and thus not very
beginner or user friendly. The expectation was that the user can
compare the input to the documentation and then infer the cause of the
error message from there. As additional aid, the error message would
include the file name of the source code where the error was triggered
and the line number. This would then allow the user to gain additional
insight from looking at the C++ source code and the embedded comments.
For other error messages and warnings, there are some more detailed
explanations in the manual for
errors and
warnings sorted
alphabetically by the message text.
But often those messages are not very detailed and specifically would not cover cases well where the same cause can trigger multiple error messages or where the same error would have multiple causes. The maintenance of this system expected that the text for the manual would be embedded in the header file "<style_name>.h" corresponding to the implementation file "<style_name>.cpp" with a specific formatting convention and then extracted, combined, and transferred into the manual with some custom scripts.
The primary goal of this approach was to reduce the effort required to maintain the larger long list of messages and keep code and manual synchronized. However, in practice this broke down because people often did not follow the convention (so errors or warnings were not documented) or changes were made to the implementation that were not reflected in the header files which in turn lead to discrepancies between code and manual. A technical reason for the non-specific error messages was the fact that the function call to trigger an error would only accept a single string. Thus any more complex and adapted error message would require to create a temporary buffer with the customized message and then pass that buffer along and release it. This would incur considerable programming effort since there are a large number of error messages.
New approach
As of LAMMPS version 4 May 2022 this approach was revised to remove the text in the header comments and instead update error messages to be more descriptive; ideally to the point where the additional explanations would become superfluous. This is supported by updating the error and warning message functions so they accept a variable number of arguments after the string message. In case of additional arguments, the string would be interpreted as a format string in style of the {fmt} formatting library. Additionally a utils::errorurl() utility function was added to direct users to longer descriptions in the manual with canonical links. Another convenience function utils::missing_cmd_args() was added for the frequent case of missing arguments to command.
This project requires many but mostly small and often trivial changes. So it is perfect for people with limited programming experience or limited experience in using git, GitHub, and contributing changes to LAMMPS. It can accommodate many contributors for as long as they coordinate on which files they operate so that there are no overlaps.
Tasks
- Replace
Illegal <something> command
with a more descriptive message. In many cases it can be sufficient to indicate which keyword of the failing command is affected or whether the keyword is unknown (which is could be due to a typo). - Similarly, when an error or warning refers to a missing or invalid group, molecule, variable, compute, fix, or dump ID augment the error message to include the name.
- For missing arguments use the utils::missing_cmd_args() convenience function
- For errors on file operations, the error message would ideally include the file name (if available in the scope) and the error text from the utils::getsyserror() function
- For errors requiring complex explanations add a new paragraph to the doc/src/Errors_details.rst file and insert a call to utils::errorurl() utility function. To complete the functionality the LAMMPS developers need to expand the “jump table” for such canonical error URLs on the https://docs.lammps.org webserver.
Examples
- Old:
if (sortfreq < 0 || userbinsize < 0.0)
error->all(FLERR,"Illegal atom_modify command");
} else error->all(FLERR,"Illegal atom_modify command");
- New
if (sortfreq < 0) error->all(FLERR,"Illegal atom_modify sort frequency {}", sortfreq);
if (userbinsize < 0.0) error->all(FLERR,"Illegal atom_modify sort bin size {}", userbinsize);
} else error->all(FLERR,"Illegal atom_modify command argument: {}", arg[iarg]);
- Old:
error->all(FLERR,"Could not find atom_modify first group ID");
- New
error->all(FLERR,"Could not find atom_modify first group ID {}", firstgroupname);
- Old:
if (narg == 0) error->all(FLERR,"Illegal atom_modify command");
if (iarg+2 > narg) error->all(FLERR,"Illegal atom_modify command");
- New
if (narg == 0) utils::missing_cmd_args(FLERR, "atom_modify", error);
if (iarg+2 > narg) utils::missing_cmd_args(FLERR, "atom_modify id", error);
- Old:
if (!fp) error->one(FLERR,"Cannot open compressed file for reading");
- New
if (!fp) error->one(FLERR, "Cannot open file {}: {}", file, utils::getsyserror());
- Old:
error->all(FLERR,"Unknown identifier in data file: {}",keyword);
- New
error->all(FLERR,"Unknown identifier in data file: {}{}", keyword, utils::errorurl(1));
.. _err0001:
Unknown identifier in data file
-------------------------------
This error happens when LAMMPS encounters a line of text in an unexpected format
[...]