Skip to content

fix: avoid panic when a parameter override is an empty YAML array#637

Closed
Lots-ninety-nine wants to merge 1 commit into
ros2-rust:mainfrom
Lots-ninety-nine:fix/empty-params-yaml-panic
Closed

fix: avoid panic when a parameter override is an empty YAML array#637
Lots-ninety-nine wants to merge 1 commit into
ros2-rust:mainfrom
Lots-ninety-nine:fix/empty-params-yaml-panic

Conversation

@Lots-ninety-nine
Copy link
Copy Markdown

@Lots-ninety-nine Lots-ninety-nine commented May 12, 2026

Fixes #636.

Problem

A parameter override declared as an empty YAML array crashes the node at executor.create_node instead of returning a recoverable error.

params.yaml:

minimal_publisher:
  ros__parameters:
    my_param: []
$ ros2 run examples_rclrs_minimal_pub_sub minimal_publisher \
    --ros-args --params-file params.yaml

thread 'main' panicked at rclrs/src/parameter/value.rs:458:9:
assertion `left == right` failed
  left: 0
 right: 1
stack backtrace:
   0: __rustc::rust_begin_unwind
   1: core::panicking::panic_fmt
   2: core::panicking::assert_failed_inner
   3: core::panicking::assert_failed
   4: rclrs::parameter::value::ParameterValue::from_rcl_variant
   5: rclrs::parameter::override_map::resolve_parameter_overrides
   6: rclrs::parameter::ParameterInterface::new
   7: rclrs::node::node_options::NodeOptions::build
   8: rclrs::executor::Executor::create_node
   9: minimal_publisher::main

Root cause

ParameterValue::from_rcl_variant expects exactly one of the nine type-specific pointers on rcl_variant_t to be non-null. For an empty YAML array the rcl YAML parser cannot infer the element type, so it emits a variant with all nine of those pointers null. The function then hits assert_eq!(num_active, 1) and panics.

The same from_rcl_variant is reached for every parameter override that the node sees, so any node that is started with a parameters file containing a single [] entry will fail to start at all — including nodes that do not even declare that parameter.

Fix

Change from_rcl_variant to return Option<Self> and return None when the variant has zero (or, hypothetically, more than one) active fields. The single in-tree caller — resolve_parameter_overrides in override_map.rs — now skips overrides whose type could not be determined:

if let Some(value) = ParameterValue::from_rcl_variant(variant) {
    map.insert(param_name, value);
}

Rationale for silently dropping rather than surfacing a brand new error variant:

  • The node still starts, which matches the behavior users expect when most of their parameters file is well-formed.
  • If a node actually requires the ambiguous parameter, the existing DeclarationError::NoValueAvailable will fire at declare_parameter time and point at the specific parameter, which is more actionable than a panic during construction.
  • The change keeps from_rcl_variant pub(crate) and does not add a new variant to RclrsError, so the public API surface is unchanged.

The existing in-module test for from_rcl_variant is adjusted to .expect(...) since the variants it constructs are always well-formed.

Verification

Unit tests

Added a regression test test_resolve_parameter_overrides_skips_empty_array that loads:

/my_ns/my_node:
    ros__parameters:
        good_int: 7
        empty_array: []

and asserts:

  • good_int is present with value Integer(7),
  • empty_array is not in the override map,
  • no panic occurs.

Full rclrs test suite locally:

test result: ok. 119 passed; 0 failed; 0 ignored; 0 measured

End-to-end

With the same params.yaml from the bug report, after the fix:

$ ros2 run examples_rclrs_minimal_pub_sub minimal_publisher \
    --ros-args --params-file params.yaml
Publishing: [Hello, world! 1]
Publishing: [Hello, world! 2]
Publishing: [Hello, world! 3]
...

Tested on:

  • Ubuntu 24.04 (Noble), ROS 2 Jazzy
  • rustc 1.86 stable, cargo-ament-build 0.1

@Lots-ninety-nine Lots-ninety-nine force-pushed the fix/empty-params-yaml-panic branch 2 times, most recently from 6e136da to 9c59d24 Compare May 12, 2026 10:12
Specifying `my_param: []` in a node parameters file made the rcl YAML
parser emit an `rcl_variant_t` with no type-specific pointer set, since
it cannot infer an element type from an empty array. The previous
`assert_eq!(num_active, 1)` inside `ParameterValue::from_rcl_variant`
turned this into a panic during `executor.create_node`.

Change `from_rcl_variant` to return `Option<Self>` and skip ambiguous
variants in `resolve_parameter_overrides`, so the node can still start.
If the parameter is actually required, the user will get a clearer
`DeclarationError::NoValueAvailable` later at `declare_parameter` time.

Adds a regression test that loads a YAML file with both a well-formed
override and an empty array and verifies the empty entry is dropped
while the rest is preserved.

Fixes ros2-rust#636
@Lots-ninety-nine Lots-ninety-nine force-pushed the fix/empty-params-yaml-panic branch from 9c59d24 to cc5176d Compare May 12, 2026 10:21
@Lots-ninety-nine Lots-ninety-nine deleted the fix/empty-params-yaml-panic branch May 12, 2026 10:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Panic on empty list in params.yaml

1 participant