automation: an array where the output goes is no output either (#2479)

`file.createProxy` and `renderQueue.add` read a single string (`str_p`), so
`{path: ["…/a.mov"]}` leaves them on their default while the confinement saw a
path it could check and let the queue go ahead: on an unsaved project that was
`~/Movies/A_proxy.mov` again. Only a plain string now counts as an output the
agent named.

Found by CodeRabbit on the pull request, which reported it fixed by 9cc23209;
it was not, and the case is in the test now.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
Anubhav RaiandClaude Opus 5 committed 2026-10-28 00:03:47 +05:30
1 parent 9cc232096c
commit 80a33f0e86
2 files changed
+8 -3

No files matched your search

+4 -3
View File
@@ -169,8 +169,9 @@ impl Confinement {
(None, None) => (&[][..], Access::Read),
};
let mut given = false;
// Whether one of them is a file and not a Render Queue template, whose own output is
// relative and resolved like one the agent never gave.
// Whether one of them is a file: not a Render Queue template, whose own output is relative
// and resolved like one the agent never gave, and not an array, which the commands that
// take a single output read as nothing at all.
let mut gave_a_file = false;
for key in named {
let Some(v) = params.get(*key).filter(|v| !v.is_null()) else { continue };
@@ -184,7 +185,7 @@ impl Confinement {
match p.as_str() {
Some(s) if id == "render.preRender" && !looks_like_path(s) => {}
Some(s) => {
gave_a_file = true;
gave_a_file |= v.is_string();
self.check(s, access)?;
}
None => return Err(Error::BadArgs(format!("`{id}`: `{key}` must be a path"))),
+4
View File
@@ -1402,6 +1402,10 @@ fn automation_roots_refuse_a_queued_output_from_an_unsaved_project() {
let msg = c[0]["text"].as_str().unwrap_or_default();
assert!(msg.contains("the project has no file yet"), "`{command}`: {msg}");
}
// An array where a path goes: the engine reads a scalar, so this is no output either.
let (c, err) = call(&mut s, "execute_command", json!({"command": "file.createProxy", "params": {"comp": "A", "path": [p("arr.mov")]}}));
assert!(err, "an array where the output goes should be refused: {c:?}");
assert!(c[0]["text"].as_str().unwrap_or_default().contains("the project has no file yet"), "{c:?}");
// Naming an Output Module template instead of a file is the same: its own output is relative.
let (c, err) = call(&mut s, "execute_command", json!({"command": "render.preRender", "params": {"comp": "A", "output": "Lossless"}}));
assert!(err, "a template output should be refused too: {c:?}");