diff --git a/reframe/utility/__init__.py b/reframe/utility/__init__.py
index aa678bce..f6b7d664 100644
--- a/reframe/utility/__init__.py
+++ b/reframe/utility/__init__.py
@@ -836,6 +836,9 @@ class _NodeGroup:
         self.__nodes.append(nid)
 
     def __str__(self):
+        if not self.__nodes:
+            return self.__name
+
         abbrev = []
         encoded = _rl_encode(_delta_encode(self.nodes))
         for unit in encoded:
@@ -920,7 +923,8 @@ def nodelist_abbrev(nodes):
         basename, width, nid = _parse_node(n)
         ng = _NodeGroup(basename, width)
         node_groups.setdefault(ng, ng)
-        node_groups[ng].add(nid)
+        if nid is not None:
+            node_groups[ng].add(nid)
 
     return ','.join(str(ng) for ng in node_groups)
 

diff --git a/unittests/test_utility.py b/unittests/test_utility.py
index 4e9f8fe7..d3392b8d 100644
--- a/unittests/test_utility.py
+++ b/unittests/test_utility.py
@@ -1800,6 +1800,8 @@ def test_nodelist_utilities():
     assert nodelist(['nid01', 'nid10', 'nid20']) == 'nid01,nid10,nid20'
     assert nodelist([]) == ''
     assert nodelist(['nid001']) == 'nid001'
+    assert nodelist(['node']) == 'node'
+    assert nodelist(['nid001', 'node', 'nid002']) == 'nid00[1-2],node'
 
     # Test the reverse operation
     assert expand('nid00[0-4],nid01[0-4],nid02[0-4]') == sorted(nid_nodes)

Nodelist in failure report adds a `None` at the end
This is very easy to reproduce:

```
./bin/reframe -c unittests/resources/checks/hellocheck.py -S 'prerun_cmds=set -e;foo' -r
```

```
FAILURE INFO for HelloTest
  * Expanded name: HelloTest
  * Description: C Hello World test
  * System partition: generic:default
  * Environment: builtin
  * Stage directory: /Users/karakasv/Repositories/reframe/stage/generic/default/builtin/HelloTest
  * Node list: tresa.localNone
  * Job type: local (id=80795)
  * Dependencies (conceptual): []
  * Dependencies (actual): []
  * Maintainers: ['VK']
  * Failing phase: sanity
  * Rerun with '-n /2b3e4546 -p builtin --system generic:default -r'
  * Reason: sanity error: pattern 'Hello, World\\!' not found in 'rfm_job.out'
```
unittests/test_utility.py::test_nodelist_utilities
unittests/test_utility.py::test_command_success unittests/test_utility.py::test_command_success_cmd_seq unittests/test_utility.py::test_command_error unittests/test_utility.py::test_command_error_cmd_seq unittests/test_utility.py::test_command_timeout unittests/test_utility.py::test_command_stdin unittests/test_utility.py::test_command_async unittests/test_utility.py::test_copytree unittests/test_utility.py::test_copytree_src_parent_of_dst unittests/test_utility.py::test_copytree_dst_notdir[dirs_exist_ok=True] unittests/test_utility.py::test_copytree_dst_notdir[dirs_exist_ok=False] unittests/test_utility.py::test_copytree_src_notdir[dirs_exist_ok=True] unittests/test_utility.py::test_copytree_src_notdir[dirs_exist_ok=False] unittests/test_utility.py::test_copytree_src_does_not_exist[dirs_exist_ok=True] unittests/test_utility.py::test_copytree_src_does_not_exist[dirs_exist_ok=False] unittests/test_utility.py::test_rmtree unittests/test_utility.py::test_rmtree_onerror unittests/test_utility.py::test_rmtree_error unittests/test_utility.py::test_inpath unittests/test_utility.py::test_subdirs unittests/test_utility.py::test_samefile unittests/test_utility.py::test_is_interactive unittests/test_utility.py::test_is_url unittests/test_utility.py::test_git_repo_hash unittests/test_utility.py::test_git_repo_hash_no_git unittests/test_utility.py::test_git_repo_hash_no_git_repo unittests/test_utility.py::test_git_repo_exists unittests/test_utility.py::test_force_remove_file unittests/test_utility.py::test_expandvars_dollar unittests/test_utility.py::test_expandvars_backticks unittests/test_utility.py::test_expandvars_mixed_syntax unittests/test_utility.py::test_expandvars_error unittests/test_utility.py::test_strange_syntax unittests/test_utility.py::test_expandvars_nocmd unittests/test_utility.py::test_virtual_copy_nolinks unittests/test_utility.py::test_virtual_copy_nolinks_dirs_exist unittests/test_utility.py::test_virtual_copy_valid_links unittests/test_utility.py::test_virtual_copy_inexistent_links unittests/test_utility.py::test_virtual_copy_absolute_paths unittests/test_utility.py::test_virtual_copy_irrelevant_paths unittests/test_utility.py::test_virtual_copy_linkself unittests/test_utility.py::test_virtual_copy_linkparent unittests/test_utility.py::test_virtual_copy_symlinks_dirs_exist[symlinks=True] unittests/test_utility.py::test_virtual_copy_symlinks_dirs_exist[symlinks=False] unittests/test_utility.py::test_import_from_file_load_relpath unittests/test_utility.py::test_import_from_file_load_directory unittests/test_utility.py::test_import_from_file_load_abspath unittests/test_utility.py::test_import_from_file_existing_module_name unittests/test_utility.py::test_import_from_file_load_directory_relative unittests/test_utility.py::test_import_from_file_load_relative unittests/test_utility.py::test_import_from_file_load_twice unittests/test_utility.py::test_import_from_file_load_namespace_package unittests/test_utility.py::test_ppretty_simple_types unittests/test_utility.py::test_ppretty_mixed_types unittests/test_utility.py::test_ppretty_obj_print unittests/test_utility.py::test_repr_default unittests/test_utility.py::test_attrs unittests/test_utility.py::test_change_dir_working unittests/test_utility.py::test_exception_propagation unittests/test_utility.py::test_allx unittests/test_utility.py::test_decamelize unittests/test_utility.py::test_sanitize unittests/test_utility.py::test_scoped_dict_construction unittests/test_utility.py::test_scoped_dict_contains unittests/test_utility.py::test_scoped_dict_iter_keys unittests/test_utility.py::test_scoped_dict_iter_items unittests/test_utility.py::test_scoped_dict_iter_values unittests/test_utility.py::test_scoped_dict_key_resolution unittests/test_utility.py::test_scoped_dict_setitem unittests/test_utility.py::test_scoped_dict_delitem unittests/test_utility.py::test_scoped_dict_scope_key_name_pseudoconflict unittests/test_utility.py::test_scoped_dict_update unittests/test_utility.py::test_sequence_view unittests/test_utility.py::test_mapping_view unittests/test_utility.py::test_shortest_sequence unittests/test_utility.py::test_longest_sequence unittests/test_utility.py::test_ordered_set_construction unittests/test_utility.py::test_ordered_set_construction_empty unittests/test_utility.py::test_ordered_set_str unittests/test_utility.py::test_ordered_set_construction_error unittests/test_utility.py::test_ordered_set_repr unittests/test_utility.py::test_ordered_set_operators unittests/test_utility.py::test_ordered_set_union unittests/test_utility.py::test_ordered_set_intersection unittests/test_utility.py::test_ordered_set_difference unittests/test_utility.py::test_ordered_set_reversed unittests/test_utility.py::test_concat_files unittests/test_utility.py::test_unique_abs_paths unittests/test_utility.py::test_cray_cdt_version unittests/test_utility.py::test_cray_cdt_version_unknown_fmt unittests/test_utility.py::test_cray_cdt_version_empty_file unittests/test_utility.py::test_cray_cdt_version_no_such_file unittests/test_utility.py::test_cray_cle_info unittests/test_utility.py::test_cray_cle_info_no_such_file unittests/test_utility.py::test_cray_cle_info_missing_parts unittests/test_utility.py::test_find_modules[nomod] unittests/test_utility.py::test_find_modules_env_mapping[nomod] unittests/test_utility.py::test_find_modules_errors unittests/test_utility.py::test_jsonext_dump unittests/test_utility.py::test_jsonext_dumps unittests/test_utility.py::test_jsonext_load unittests/test_utility.py::test_attr_validator unittests/test_utility.py::test_is_picklable unittests/test_utility.py::test_is_copyable unittests/test_utility.py::test_is_trivially_callable unittests/test_utility.py::test_cached_return_value