tracel-ai/burn · error

Standard deviation is required to be non-negative, but got {

Error message

Standard deviation is required to be non-negative, but got {}

What it means

GaussianNoiseConfig::init in burn-nn panics when the configured standard deviation is negative (std.is_sign_negative() is true, which also catches -0.0). A Gaussian noise layer is parameterized by a standard deviation, which is mathematically undefined for negative values, so the library rejects the config at initialization time rather than producing undefined sampling behavior later.

Source

Thrown at crates/burn-nn/src/modules/noise.rs:36

/// distortion.
///
/// Should be created with [GaussianNoiseConfig].
#[derive(Module, Debug)]
#[module(custom_display)]
pub struct GaussianNoise {
    /// Standard deviation of the normal noise distribution.
    pub std: f64,
    /// Whether to behave as during training. Cleared by
    /// [`freeze`](burn::module::Module::freeze) and matching
    /// [`freeze_group`](burn::module::Module::freeze_group) traversals.
    pub training: Param<Flag>,
}

impl GaussianNoiseConfig {
    /// Initialize a new [Gaussian noise](GaussianNoise) module.
    pub fn init(&self) -> GaussianNoise {
        if self.std.is_sign_negative() {
            panic!(
                "Standard deviation is required to be non-negative, but got {}",
                self.std
            );
        }
        GaussianNoise {
            std: self.std,
            training: Param::from_bool(true),
        }
    }
}

impl GaussianNoise {
    /// Applies the forward pass on the input tensor.
    ///
    /// See [GaussianNoise](GaussianNoise) for more information.
    ///
    /// # Shapes
    ///

View on GitHub (pinned to d16f7ba2ed)

Solutions

  1. Pass a non-negative standard deviation to GaussianNoiseConfig::new(...) (strictly positive if you want actual noise; use 0.0 to disable).
  2. Clamp computed values: std = std.max(0.0) before constructing the config.
  3. If std comes from a sweep or external config, validate range (0.0..=upper_bound) before init().
  4. Check for accidental sign flips in the expression that produces std.

Example fix

// before
let cfg = GaussianNoiseConfig::new(-0.5);
let noise = cfg.init(); // panics
// after
let sigma = 0.5_f64.max(0.0);
let cfg = GaussianNoiseConfig::new(sigma);
let noise = cfg.init();
Defensive patterns

Strategy: validation

Validate before calling

// before GaussianNoiseConfig::init()
assert!(!std_dev.is_sign_negative(), "std must be non-negative, got {}", std_dev);

Type guard

fn is_valid_std(std: f64) -> bool {
    std.is_finite() && !std.is_sign_negative()
}

Try / catch

let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| config.init()));
match result {
    Ok(module) => module,
    Err(_) => GaussianNoiseConfig::new(0.0).init(), // noise disabled fallback
}

Prevention

When it happens

Trigger: Calling GaussianNoiseConfig::init() (or building it via GaussianNoiseConfig::new(std)) with a negative std, e.g. GaussianNoiseConfig::new(-0.5). Also triggered by std = -0.0, or a std computed from a formula/sign-flip (e.g. -temperature, 1.0 - x where x > 1) that went negative at runtime.

Common situations: Sign errors when wiring hyperparameters (noise = -sigma), loading noise magnitude from a config file with a stray minus sign, computing std as a difference that underflows below zero (e.g. start_noise - end_noise with swapped bounds), or hand-tuned sweeps that iterate sigma over a range including negatives.

Related errors


AI-assisted analysis of tracel-ai/burn@d16f7ba2ed (2026-09-05). Data as JSON: /api/errors/25f10a405a9bf98e. Report an issue: GitHub.