diff --git a/daemons/ganeti-noded b/daemons/ganeti-noded
index 15af1014c4a80d3e36a10d488ac90d854d584f95..b9b51df80d72b009ac661d3c23dcd749ef274f36 100755
--- a/daemons/ganeti-noded
+++ b/daemons/ganeti-noded
@@ -608,7 +608,7 @@ class NodeHttpServer(http.server.HttpServer):
     """Query detailed information about existing OSes.
 
     """
-    return True, [os_obj.ToDict() for os_obj in backend.DiagnoseOS()]
+    return backend.DiagnoseOS()
 
   @staticmethod
   def perspective_os_get(params):
@@ -616,11 +616,8 @@ class NodeHttpServer(http.server.HttpServer):
 
     """
     name = params[0]
-    try:
-      os_obj = backend.OSFromDisk(name)
-    except errors.InvalidOS, err:
-      os_obj = objects.OS.FromInvalidOS(err)
-    return os_obj.ToDict()
+    os_obj = backend.OSFromDisk(name)
+    return True, os_obj.ToDict()
 
   # hooks -----------------------
 
diff --git a/lib/backend.py b/lib/backend.py
index e5077c1717f6e6c8a56cd11443e37dc7b7e2e889..bf6316865fa77088aaf89ac351905ab80283b4c4 100644
--- a/lib/backend.py
+++ b/lib/backend.py
@@ -718,15 +718,8 @@ def InstanceOsAdd(instance, reinstall):
   @return: the success of the operation
 
   """
-  try:
-    inst_os = OSFromDisk(instance.os)
-  except errors.InvalidOS, err:
-    os_name, os_dir, os_err = err.args
-    if os_dir is None:
-      return (False, "Can't find OS '%s': %s" % (os_name, os_err))
-    else:
-      return (False, "Error parsing OS '%s' in directory %s: %s" %
-              (os_name, os_dir, os_err))
+  inst_os = OSFromDisk(instance.os)
+
 
   create_env = OSEnvironment(instance)
   if reinstall:
@@ -1530,12 +1523,12 @@ def _OSOndiskVersion(name, os_dir):
   try:
     st = os.stat(api_file)
   except EnvironmentError, err:
-    raise errors.InvalidOS(name, os_dir, "'ganeti_api_version' file not"
-                           " found (%s)" % _ErrnoOrStr(err))
+    return False, ("Required file 'ganeti_api_version' file not"
+                   " found under path %s: %s" % (os_dir, _ErrnoOrStr(err)))
 
   if not stat.S_ISREG(stat.S_IFMT(st.st_mode)):
-    raise errors.InvalidOS(name, os_dir, "'ganeti_api_version' file is not"
-                           " a regular file")
+    return False, ("File 'ganeti_api_version' file at %s is not"
+                   " a regular file" % os_dir)
 
   try:
     f = open(api_file)
@@ -1544,17 +1537,17 @@ def _OSOndiskVersion(name, os_dir):
     finally:
       f.close()
   except EnvironmentError, err:
-    raise errors.InvalidOS(name, os_dir, "error while reading the"
-                           " API version (%s)" % _ErrnoOrStr(err))
+    return False, ("Error while reading the API version file at %s: %s" %
+                   (api_file, _ErrnoOrStr(err)))
 
   api_versions = [version.strip() for version in api_versions]
   try:
     api_versions = [int(version) for version in api_versions]
   except (TypeError, ValueError), err:
-    raise errors.InvalidOS(name, os_dir,
-                           "API version is not integer (%s)" % str(err))
+    return False, ("API version(s) can't be converted to integer: %s" %
+                   str(err))
 
-  return api_versions
+  return True, api_versions
 
 
 def DiagnoseOS(top_dirs=None):
@@ -1565,8 +1558,12 @@ def DiagnoseOS(top_dirs=None):
       search (if not given defaults to
       L{constants.OS_SEARCH_PATH})
   @rtype: list of L{objects.OS}
-  @return: an OS object for each name in all the given
-      directories
+  @return: a list of tuples (name, path, status, diagnose)
+      for all (potential) OSes under all search paths, where:
+          - name is the (potential) OS name
+          - path is the full path to the OS
+          - status True/False is the validity of the OS
+          - diagnose is the error message for an invalid OS, otherwise empty
 
   """
   if top_dirs is None:
@@ -1581,16 +1578,18 @@ def DiagnoseOS(top_dirs=None):
         logging.exception("Can't list the OS directory %s", dir_name)
         break
       for name in f_names:
-        try:
-          os_inst = OSFromDisk(name, base_dir=dir_name)
-          result.append(os_inst)
-        except errors.InvalidOS, err:
-          result.append(objects.OS.FromInvalidOS(err))
+        os_path = os.path.sep.join([dir_name, name])
+        status, os_inst = _TryOSFromDisk(name, base_dir=dir_name)
+        if status:
+          diagnose = ""
+        else:
+          diagnose = os_inst
+        result.append((name, os_path, status, diagnose))
 
-  return result
+  return True, result
 
 
-def OSFromDisk(name, base_dir=None):
+def _TryOSFromDisk(name, base_dir=None):
   """Create an OS instance from disk.
 
   This function will return an OS instance if the given name is a
@@ -1600,24 +1599,26 @@ def OSFromDisk(name, base_dir=None):
   @type base_dir: string
   @keyword base_dir: Base directory containing OS installations.
                      Defaults to a search in all the OS_SEARCH_PATH dirs.
-  @rtype: L{objects.OS}
-  @return: the OS instance if we find a valid one
-  @raise errors.InvalidOS: if we don't find a valid OS
+  @rtype: tuple
+  @return: success and either the OS instance if we find a valid one,
+      or error message
 
   """
   if base_dir is None:
     os_dir = utils.FindFile(name, constants.OS_SEARCH_PATH, os.path.isdir)
     if os_dir is None:
-      raise errors.InvalidOS(name, None, "OS dir not found in search path")
+      return False, "Directory for OS %s not found in search path" % name
   else:
     os_dir = os.path.sep.join([base_dir, name])
 
-  api_versions = _OSOndiskVersion(name, os_dir)
+  status, api_versions = _OSOndiskVersion(name, os_dir)
+  if not status:
+    # push the error up
+    return status, api_versions
 
   if constants.OS_API_VERSION not in api_versions:
-    raise errors.InvalidOS(name, os_dir, "API version mismatch"
-                           " (found %s want %s)"
-                           % (api_versions, constants.OS_API_VERSION))
+    return False, ("API version mismatch for path '%s': found %s, want %s." %
+                   (os_dir, api_versions, constants.OS_API_VERSION))
 
   # OS Scripts dictionary, we will populate it with the actual script names
   os_scripts = dict.fromkeys(constants.OS_SCRIPTS)
@@ -1628,24 +1629,51 @@ def OSFromDisk(name, base_dir=None):
     try:
       st = os.stat(os_scripts[script])
     except EnvironmentError, err:
-      raise errors.InvalidOS(name, os_dir, "'%s' script missing (%s)" %
-                             (script, _ErrnoOrStr(err)))
+      return False, ("Script '%s' under path '%s' is missing (%s)" %
+                     (script, os_dir, _ErrnoOrStr(err)))
 
     if stat.S_IMODE(st.st_mode) & stat.S_IXUSR != stat.S_IXUSR:
-      raise errors.InvalidOS(name, os_dir, "'%s' script not executable" %
-                             script)
+      return False, ("Script '%s' under path '%s' is not executable" %
+                     (script, os_dir))
 
     if not stat.S_ISREG(stat.S_IFMT(st.st_mode)):
-      raise errors.InvalidOS(name, os_dir, "'%s' is not a regular file" %
-                             script)
+      return False, ("Script '%s' under path '%s' is not a regular file" %
+                     (script, os_dir))
+
+  os_obj = objects.OS(name=name, path=os_dir, status=constants.OS_VALID_STATUS,
+                      create_script=os_scripts[constants.OS_SCRIPT_CREATE],
+                      export_script=os_scripts[constants.OS_SCRIPT_EXPORT],
+                      import_script=os_scripts[constants.OS_SCRIPT_IMPORT],
+                      rename_script=os_scripts[constants.OS_SCRIPT_RENAME],
+                      api_versions=api_versions)
+  return True, os_obj
+
+
+def OSFromDisk(name, base_dir=None):
+  """Create an OS instance from disk.
+
+  This function will return an OS instance if the given name is a
+  valid OS name. Otherwise, it will raise an appropriate
+  L{RPCFail} exception, detailing why this is not a valid OS.
+
+  This is just a wrapper over L{_TryOSFromDisk}, which doesn't raise
+  an exception but returns true/false status data.
+
+  @type base_dir: string
+  @keyword base_dir: Base directory containing OS installations.
+                     Defaults to a search in all the OS_SEARCH_PATH dirs.
+  @rtype: L{objects.OS}
+  @return: the OS instance if we find a valid one
+  @raise RPCFail: if we don't find a valid OS
+
+  """
+  status, payload = _TryOSFromDisk(name, base_dir)
+
+  if not status:
+    _Fail(payload)
 
+  return payload
 
-  return objects.OS(name=name, path=os_dir, status=constants.OS_VALID_STATUS,
-                    create_script=os_scripts[constants.OS_SCRIPT_CREATE],
-                    export_script=os_scripts[constants.OS_SCRIPT_EXPORT],
-                    import_script=os_scripts[constants.OS_SCRIPT_IMPORT],
-                    rename_script=os_scripts[constants.OS_SCRIPT_RENAME],
-                    api_versions=api_versions)
 
 def OSEnvironment(instance, debug=0):
   """Calculate the environment for an os script.
diff --git a/lib/cmdlib.py b/lib/cmdlib.py
index 0676c2383c1714b8e295d40fc9bd49c4739672be..d983365b9507165bccf417b6822326e04540eaae 100644
--- a/lib/cmdlib.py
+++ b/lib/cmdlib.py
@@ -1801,10 +1801,11 @@ class LUDiagnoseOS(NoHooksLU):
 
     @rtype: dict
     @return: a dictionary with osnames as keys and as value another map, with
-        nodes as keys and list of OS objects as values, eg::
+        nodes as keys and tuples of (path, status, diagnose) as values, eg::
 
-          {"debian-etch": {"node1": [<object>,...],
-                           "node2": [<object>,]}
+          {"debian-etch": {"node1": [(/usr/lib/..., True, ""),
+                                     (/srv/..., False, "invalid api")],
+                           "node2": [(/srv/..., True, "")]}
           }
 
     """
@@ -1817,15 +1818,14 @@ class LUDiagnoseOS(NoHooksLU):
     for node_name, nr in rlist.items():
       if nr.RemoteFailMsg() or not nr.payload:
         continue
-      for os_serialized in nr.payload:
-        os_obj = objects.OS.FromDict(os_serialized)
-        if os_obj.name not in all_os:
+      for name, path, status, diagnose in nr.payload:
+        if name not in all_os:
           # build a list of nodes for this os containing empty lists
           # for each node in node_list
-          all_os[os_obj.name] = {}
+          all_os[name] = {}
           for nname in good_nodes:
-            all_os[os_obj.name][nname] = []
-        all_os[os_obj.name][node_name].append(os_obj)
+            all_os[name][nname] = []
+        all_os[name][node_name].append((path, status, diagnose))
     return all_os
 
   def Exec(self, feedback_fn):
@@ -1842,11 +1842,12 @@ class LUDiagnoseOS(NoHooksLU):
         if field == "name":
           val = os_name
         elif field == "valid":
-          val = utils.all([osl and osl[0] for osl in os_data.values()])
+          val = utils.all([osl and osl[0][1] for osl in os_data.values()])
         elif field == "node_status":
+          # this is just a copy of the dict
           val = {}
-          for node_name, nos_list in os_data.iteritems():
-            val[node_name] = [(v.status, v.path) for v in nos_list]
+          for node_name, nos_list in os_data.items():
+            val[node_name] = nos_list
         else:
           raise errors.ParameterError(field)
         row.append(val)
@@ -3156,10 +3157,11 @@ class LUReinstallInstance(LogicalUnit):
         raise errors.OpPrereqError("Primary node '%s' is unknown" %
                                    self.op.pnode)
       result = self.rpc.call_os_get(pnode.name, self.op.os_type)
-      result.Raise()
-      if not isinstance(result.data, objects.OS):
+      msg = result.RemoteFailMsg()
+      if msg:
         raise errors.OpPrereqError("OS '%s' not in supported OS list for"
-                                   " primary node"  % self.op.os_type)
+                                   " primary node %s: %s"  %
+                                   (self.op.os_type, pnode.pname, msg))
 
     self.instance = instance
 
@@ -4843,10 +4845,11 @@ class LUCreateInstance(LogicalUnit):
 
     # os verification
     result = self.rpc.call_os_get(pnode.name, self.op.os_type)
-    result.Raise()
-    if not isinstance(result.data, objects.OS):
+    msg = result.RemoteFailMsg()
+    if msg:
       raise errors.OpPrereqError("OS '%s' not in supported os list for"
-                                 " primary node"  % self.op.os_type)
+                                 " primary node %s: %s"  %
+                                 (self.op.os_type, pnode.name, msg))
 
     _CheckNicsBridgesExist(self, self.nics, self.pnode.name)
 
diff --git a/scripts/gnt-os b/scripts/gnt-os
index a0c09a7abac0d4c49fb56ad437bacf22550ab6ff..4cfa07bf0e307fd0feaa366df6bdfe77aedd9d4e 100755
--- a/scripts/gnt-os
+++ b/scripts/gnt-os
@@ -64,6 +64,22 @@ def ListOS(opts, args):
   return 0
 
 
+def _OsStatus(status, diagnose):
+  """Beautifier function for OS status.
+
+  @type status: boolean
+  @param status: is the OS valid
+  @type diagnose: string
+  @param diagnose: the error message for invalid OSes
+  @rtype: string
+  @return: a formatted status
+
+  """
+  if status:
+    return "valid"
+  else:
+    return "invalid - %s" % diagnose
+
 def DiagnoseOS(opts, args):
   """Analyse all OSes on this cluster.
 
@@ -91,16 +107,17 @@ def DiagnoseOS(opts, args):
     for node_name, node_info in node_data.iteritems():
       nodes_hidden[node_name] = []
       if node_info: # at least one entry in the per-node list
-        first_os_status, first_os_path = node_info.pop(0)
-        first_os_msg = ("%s (path: %s)" %
-                        (first_os_status, first_os_path))
-        if first_os_status == constants.OS_VALID_STATUS:
+        first_os_path, first_os_status, first_os_msg = node_info.pop(0)
+        first_os_msg = ("%s (path: %s)" % (_OsStatus(first_os_status,
+                                                     first_os_msg),
+                                           first_os_path))
+        if first_os_status:
           nodes_valid[node_name] = first_os_msg
         else:
           nodes_bad[node_name] = first_os_msg
-        for hstatus, hpath in node_info:
+        for hpath, hstatus, hmsg in node_info:
           nodes_hidden[node_name].append("    [hidden] path: %s, status: %s" %
-                                         (hpath, hstatus))
+                                         (hpath, _OsStatus(hstatus, hmsg)))
       else:
         nodes_bad[node_name] = "OS not found"