<#21262 Hard native parser errors cause 2.22 to fa...
# github-notifications
c
#21262 Hard native parser errors cause 2.22 to fail to start, ignores `native_option_validation=warning` Issue created by huonw Describe the bug In 2.22.0.dev2 and newer, a float option given an integer-format value like
1
fails to start, with a hard "Exception: Expected ... to be a float but given 1" error, and this isn't handled gracefully. The workaround is either: • fix the specific problem (e.g. add
.0
, like
1.0
) • set
[GLOBAL].native_options_validation = "ignore"
However, this is a hard-break that makes upgrading harder. This may be related to the Rust parser, which has code that tries to paper over the difference: pants/src/rust/engine/options/src/lib.rs Lines 148 to 156 in</pantsbuild/pants/commit/a2acb196216ce5cabe45ee6a039eb5d5f530777a|a2acb19> | if let Some(value) = self.get_string(id)? { | | ---------------------------------------------------------- | | let parsed_as_float = f64::parse(&value) | | .map(Some) | | .map_err(\|e| e.render(self.display(id))); | | if parsed_as_float.is_err() { | | // See if we can parse as an int and coerce it to a float. | | if let Ok(i) = i64::parse(&value) { | | return Ok(Some(i as f64)); | | } | We are also theoretically just running the Rust parser in parallel, and use
[GLOBAL].native_options_validation
(https://www.pantsbuild.org/2.22/reference/global-options#native_options_validation) to control whether something is an error or not, but that's not applying in this case: setting it to
warning
doesn't downgrade the error. Reproducer: cd $(mktemp -d) cat > pants.toml <<EOF [GLOBAL] pants_version = "2.22.0.dev2" pantsd_timeout_when_multiple_invocations = 1 EOF # OK: prints the version PANTS_VERSION=2.22.0.dev1 pants version # BUG: Exception: Expected [GLOBAL] pantsd_timeout_when_multiple_invocations to be a float but given 1 pants --print-stacktrace version # BUG: still exception, not warning pants --native-options-validation=warning version Stacktrace output of the first `BUG`:
Copy code
11:16:40.86 [ERROR] 1 Exception encountered:

Engine traceback:
  in root
    ..
  in pants.core.util_rules.environments.determine_local_environment
    ..
  in pants.core.util_rules.environments.determine_all_environments
    ..
  in construct_scope_environments_preview
    ..

Traceback (most recent call last):
  File ".../pants/option/subsystem.py", line 319, in _construct_subsystem
    scoped_options = await Get(ScopedOptions, Scope(str(subsystem_typ.options_scope)))
  File ".../pants/engine/internals/selectors.py", line 124, in __await__
    result = yield self
  File ".../pants/engine/internals/options_parsing.py", line 49, in parse_options
    return _Options(options_bootstrapper, build_config, union_membership)
  File "<string>", line 6, in __init__
  File ".../pants/engine/internals/options_parsing.py", line 33, in __post_init__
    assert self.options is not None
  File ".../pants/util/memo.py", line 123, in memoize
    result = func(*args, **kwargs)
  File ".../pants/engine/internals/options_parsing.py", line 37, in options
    return self.options_bootstrapper.full_options(self.build_config, self.union_membership)
  File ".../pants/option/options_bootstrapper.py", line 310, in full_options
    GlobalOptions.validate_instance(options.for_global_scope())
  File ".../pants/option/options.py", line 529, in for_global_scope
    return self.for_scope(GLOBAL_SCOPE)
  File ".../pants/util/memo.py", line 123, in memoize
    result = func(*args, **kwargs)
  File ".../pants/option/options.py", line 396, in for_scope
    native_values = self.get_parser(scope).parse_args_native(self._native_parser)
  File ".../pants/option/parser.py", line 202, in parse_args_native
    val, rank = native_parser.get(
  File ".../pants/option/native_options.py", line 124, in get
    val, rank_int = getter(option_id, default)  # type:ignore
Exception: Expected [GLOBAL] pantsd_timeout_when_multiple_invocations to be a float but given 1

Traceback (most recent call last):
  File ".../pants/bin/daemon_pants_runner.py", line 133, in single_daemonized_run
    scheduler, options_initializer = self._core.prepare(options_bootstrapper, complete_env)
  File ".../pants/pantsd/pants_daemon_core.py", line 128, in prepare
    build_config = self._options_initializer.build_config(options_bootstrapper, env)
  File ".../pants/init/options_initializer.py", line 154, in build_config
    return _initialize_build_configuration(self._plugin_resolver, options_bootstrapper, env)
  File ".../pants/init/options_initializer.py", line 59, in _initialize_build_configuration
    working_set = plugin_resolver.resolve(options_bootstrapper, env, backends_requirements)
  File ".../pants/init/plugin_resolver.py", line 141, in resolve
    for resolved_plugin_location in self._resolve_plugins(options_bootstrapper, env, request):
  File ".../pants/init/plugin_resolver.py", line 163, in _resolve_plugins
    params = Params(request, determine_bootstrap_environment(session))
  File ".../pants/core/util_rules/environments.py", line 456, in determine_bootstrap_environment
    session.product_request(ChosenLocalEnvironmentName, [Params()])[0],
  File ".../pants/engine/internals/scheduler.py", line 585, in product_request
    return self.execute(request)
  File ".../pants/engine/internals/scheduler.py", line 526, in execute
    self._raise_on_error([t for _, t in throws])
  File ".../pants/engine/internals/scheduler.py", line 510, in _raise_on_error
    raise ExecutionError(
pants.engine.internals.scheduler.ExecutionError: 1 Exception encountered:

Engine traceback:
  in root
    ..
  in pants.core.util_rules.environments.determine_local_environment
    ..
  in pants.core.util_rules.environments.determine_all_environments
    ..
  in construct_scope_environments_preview
    ..

Traceback (most recent call last):
  File ".../pants/option/subsystem.py", line 319, in _construct_subsystem
    scoped_options = await Get(ScopedOptions, Scope(str(subsystem_typ.options_scope)))
  File ".../pants/engine/internals/selectors.py", line 124, in __await__
    result = yield self
  File ".../pants/engine/internals/options_parsing.py", line 49, in parse_options
    return _Options(options_bootstrapper, build_config, union_membership)
  File "<string>", line 6, in __init__
  File ".../pants/engine/internals/options_parsing.py", line 33, in __post_init__
    assert self.options is not None
  File ".../pants/util/memo.py", line 123, in memoize
    result = func(*args, **kwargs)
  File ".../pants/engine/internals/options_parsing.py", line 37, in options
    return self.options_bootstrapper.full_options(self.build_config, self.union_membership)
  File ".../pants/option/options_bootstrapper.py", line 310, in full_options
    GlobalOptions.validate_instance(options.for_global_scope())
  File ".../pants/option/options.py", line 529, in for_global_scope
    return self.for_scope(GLOBAL_SCOPE)
  File ".../pants/util/memo.py", line 123, in memoize
    result = func(*args, **kwargs)
  File ".../pants/option/options.py", line 396, in for_scope
    native_values = self.get_parser(scope).parse_args_native(self._native_parser)
  File ".../pants/option/parser.py", line 202, in parse_args_native
    val, rank = native_parser.get(
  File ".../pants/option/native_options.py", line 124, in get
    val, rank_int = getter(option_id, default)  # type:ignore
Exception: Expected [GLOBAL] pantsd_timeout_when_multiple_invocations to be a float but given 1
Pants version 2.22.0.dev2, 2.22.0rc2, 2.23.0.dev5 OS macOS Additional info Comparison: <https://github.com/pantsbuild/pants/compare/release_2.22.0.dev1...release_2.22.0.dev2|relea… pantsbuild/pants