Repository: conan-io/conan

Issue:
Return errorcode 6 when settings are constrained to not support the current environment
There are two approaches to restrict the environment a recipe is working for: [Constrain Settings and Options](https://docs.conan.io/en/latest/mastering/conditional.html?highlight=conaninvalidconfiguration#constrain-settings-and-options)

When using the first approach and raising a `ConanInvalidConfiguration` Conan returns with errorcode 6. This could be further processed by scripts/CI perfectly. However the second approach with constraining the settings does not return with errorcode 6, but results in an [error](http://docs.conan.io/en/latest/faq/troubleshooting.html#error-invalid-setting) and errorcode 1 instead.

Is there a reason why both return with different behaviour? It would be perfect if both would return with errorcode 6, so developers could use both methods and scripts/CI can react on that in the same way.


Discussion:

Resolving patch:
diff --git a/conans/client/loader.py b/conans/client/loader.py
--- a/conans/client/loader.py
+++ b/conans/client/loader.py
@@ -7,7 +7,7 @@
 from conans.client.generators import registered_generators
 from conans.client.loader_txt import ConanFileTextLoader
 from conans.client.tools.files import chdir
-from conans.errors import ConanException, NotFoundException
+from conans.errors import ConanException, NotFoundException, ConanInvalidConfiguration
 from conans.model.conan_file import ConanFile
 from conans.model.conan_generator import Generator
 from conans.model.options import OptionsValues
@@ -136,6 +136,8 @@ def load_conanfile(self, conanfile_path, processed_profile, ref):
         try:
             self._initialize_conanfile(conanfile, processed_profile)
             return conanfile
+        except ConanInvalidConfiguration:
+            raise
         except Exception as e:  # re-raise with file name
             raise ConanException("%s: %s" % (conanfile_path, str(e)))
 
diff --git a/conans/model/conan_file.py b/conans/model/conan_file.py
--- a/conans/model/conan_file.py
+++ b/conans/model/conan_file.py
@@ -5,7 +5,7 @@
 from conans.client.output import Color, ScopedOutput
 from conans.client.tools.env import environment_append, no_op, pythonpath
 from conans.client.tools.oss import OSInfo
-from conans.errors import ConanException
+from conans.errors import ConanException, ConanInvalidConfiguration
 from conans.model.build_info import DepsCppInfo
 from conans.model.env_info import DepsEnvInfo
 from conans.model.options import Options, OptionsValues, PackageOptions
@@ -59,7 +59,7 @@ def create_settings(conanfile, settings):
         settings.constraint(current)
         return settings
     except Exception as e:
-        raise ConanException("Error while initializing settings. %s" % str(e))
+        raise ConanInvalidConfiguration("Error while initializing settings. %s" % str(e))
 
 
 @contextmanager


Test patch:
diff --git a/conans/test/functional/command/invalid_configuration_test.py b/conans/test/functional/command/invalid_configuration_test.py
--- a/conans/test/functional/command/invalid_configuration_test.py
+++ b/conans/test/functional/command/invalid_configuration_test.py
@@ -59,3 +59,16 @@ class MyPkg(ConanFile):
         self.assertEqual(error, ERROR_INVALID_CONFIGURATION)
         self.assertIn("name/ver@jgsogo/test: Invalid configuration: user says that "
                       "compiler.version=12 is invalid", self.client.out)
+
+    def restricted_settings_raise_invalid_code_too_test(self):
+        self.client.save({"conanfile.py": """
+from conans import ConanFile
+from conans.errors import ConanInvalidConfiguration
+
+class MyPkg(ConanFile):
+    requires = "name/ver@jgsogo/test"
+    settings = {"arch": ["x86_64"]}
+"""})
+
+        error = self.client.run("create . lib/1.0@user/channel -s arch=x86", assert_error=True)
+        self.assertEqual(error, ERROR_INVALID_CONFIGURATION)