diff --git a/apps/lightcraft-cli/src/main.rs b/apps/lightcraft-cli/src/main.rs
--- a/apps/lightcraft-cli/src/main.rs
+++ b/apps/lightcraft-cli/src/main.rs
@@ -683,7 +683,9 @@ fn render(args: &[String]) -> Result<(), String> {
             "--set" => {
                 let kv = take_value(args, &mut i, "--set")?;
                 let (k, v) = kv.split_once('=').ok_or_else(|| format!("--set expects control=value, got `{kv}`"))?;
-                let v: f64 = v.trim().parse().map_err(|_| format!("--set {k}: `{v}` is not a number"))?;
+                // `inf` / `NaN` parse as f64 but become JSON null, which the control would silently ignore.
+                let v: f64 =
+                    v.trim().parse().ok().filter(|n: &f64| n.is_finite()).ok_or_else(|| format!("--set {k}: `{v}` is not a finite number"))?;
                 values.insert(k.trim().to_string(), json!(v));
             }
             "--settings" => settings = Some(read_settings(take_value(args, &mut i, "--settings")?)?),
diff --git a/apps/lightcraft-cli/tests/it/cli.rs b/apps/lightcraft-cli/tests/it/cli.rs
--- a/apps/lightcraft-cli/tests/it/cli.rs
+++ b/apps/lightcraft-cli/tests/it/cli.rs
@@ -179,6 +179,12 @@ fn render_subcommand() {
     let o = Command::new(BIN).args(["render", input.to_str().unwrap(), "-o", out.to_str().unwrap(), "--set", "nope=1"]).output().unwrap();
     assert!(!o.status.success());
     assert!(String::from_utf8_lossy(&o.stderr).contains("unknown control"));
+    // Values that parse as f64 but are not finite fail cleanly too.
+    for bad in ["light.exposure=inf", "light.exposure=-inf", "light.exposure=NaN", "light.exposure=1e999"] {
+        let o = Command::new(BIN).args(["render", input.to_str().unwrap(), "-o", out.to_str().unwrap(), "--set", bad]).output().unwrap();
+        assert!(!o.status.success(), "{bad} must be refused");
+        assert!(String::from_utf8_lossy(&o.stderr).contains("not a finite number"), "{bad}");
+    }
 }
 
 /// Issue #1730: `render --settings` took a `.lcpreset` from `preset.export`, ignored its wrapper
