Skip to content

fix(api): reject non-object params for audio::mixer in compile_dag#514

Merged
streamer45 merged 4 commits into
mainfrom
devin/1779719252-fix-mixer-non-object-params
May 27, 2026
Merged

fix(api): reject non-object params for audio::mixer in compile_dag#514
streamer45 merged 4 commits into
mainfrom
devin/1779719252-fix-mixer-non-object-params

Conversation

@staging-devin-ai-integration
Copy link
Copy Markdown
Contributor

@staging-devin-ai-integration staging-devin-ai-integration Bot commented May 25, 2026

Summary

  • compile_dag now returns Result::Err when any audio::mixer node has params that is not a JSON object, in all engine modes — not just oneshot. Dynamic pipelines previously deferred this to the node factory; now they fail at compile time too.
  • The error message includes the node name for easier debugging with multiple mixers (e.g. "audio::mixer node 'my_mixer' params must be an object, got string").
  • Updated the pinning test from PR test(api): cover yaml compiler, client_lint, and WS protocol round-trips #464 to assert the new error behavior, and added tests for dynamic mode and Some(Value::Null).

Closes #472

Review & Validation

  • cargo test -p streamkit-api -- compiler::tests passes all 6 compiler tests
  • Verify the error message includes the node name and actual type

Notes

  • Behavior change: Some(Value::Null) params (from params: null or bare params: in YAML) now errors as "got null" instead of silently skipping injection. This is intentional — null params is invalid for a mixer config and should surface early. A dedicated test pins this contract.
  • Scope: Validation is audio::mixer-only. Generalizing to all node kinds is tracked in Validate params is an object for all node kinds in compile_dag #524.

Link to Devin session: https://staging.itsdev.in/sessions/dd23569c931b41529fd43a49b50a35aa
Requested by: @streamer45


Devin Review

Status Commit
🕐 Outdated c65b88a (HEAD is 839ad23)

Run Devin Review

Open in Devin Review (Staging)

When audio::mixer params is present but not a JSON object, compile_dag
now returns an error instead of silently skipping num_inputs injection.

Closes #472

Signed-off-by: streamkit-devin <devin@streamkit.dev>
@staging-devin-ai-integration
Copy link
Copy Markdown
Contributor Author

🤖 Devin AI Engineer

I'll be helping with this pull request! Here's what you should know:

✅ I will automatically:

  • Address comments on this PR. Add '(aside)' to your comment to have me ignore it.
  • Look at CI failures and help fix them

Note: I can only respond to comments from users who have write access to this repository.

⚙️ Control Options:

  • Disable automatic comment, CI, and merge conflict monitoring

Copy link
Copy Markdown
Contributor Author

@staging-devin-ai-integration staging-devin-ai-integration Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 2 potential issues.

Open in Devin Review (Staging)
Debug

Playground

Comment thread crates/api/src/yaml/compiler.rs Outdated
Comment on lines +223 to +231
if def.kind == "audio::mixer" && mode != EngineMode::Dynamic {
if let Some(ref p) = params {
if !p.is_object() {
return Err(format!(
"audio::mixer params must be an object, got {}",
value_type_name(p),
));
}
}
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: The new params-shape rejection is limited to DAG mixer auto-injection

This check runs only for audio::mixer nodes in DAG pipelines when mode != EngineMode::Dynamic, immediately before injecting num_inputs. That means dynamic DAG pipelines and all steps: pipelines preserve their previous compile-time behavior; dynamic audio::mixer params are still left to the node factory/engine path rather than being normalized here. This appears consistent with the existing dynamic-mode test and with AudioMixerConfig needing num_inputs only for stateless/oneshot pre-created pins (crates/nodes/src/audio/filters/mixer.rs:63-64).

Open in Devin Review (Staging)

Was this helpful? React with 👍 or 👎 to provide feedback.

Debug

Playground

Comment on lines +258 to +260
Ok((name, Node { kind: def.kind, params, state: None }))
})
.collect();
.collect::<Result<IndexMap<_, _>, _>>()?;
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Collecting into a Result preserves successful pipeline construction semantics

Changing the node-map construction from collecting bare (name, Node) pairs to collecting Result<(name, Node), String> only introduces early return on the new validation failure. The connection list and incoming counts are fully built before this point, and user_nodes.into_iter() is still consumed exactly once, so successful compilations keep the same node ordering and connection data as before.

Open in Devin Review (Staging)

Was this helpful? React with 👍 or 👎 to provide feedback.

Debug

Playground

@codecov
Copy link
Copy Markdown

codecov Bot commented May 25, 2026

Codecov Report

❌ Patch coverage is 89.85507% with 7 lines in your changes missing coverage. Please review.
✅ Project coverage is 79.41%. Comparing base (6bebdbb) to head (839ad23).

Files with missing lines Patch % Lines
crates/api/src/yaml/compiler.rs 89.85% 7 Missing ⚠️
Additional details and impacted files
@@           Coverage Diff           @@
##             main     #514   +/-   ##
=======================================
  Coverage   79.41%   79.41%           
=======================================
  Files         232      232           
  Lines       66904    66951   +47     
  Branches     1822     1908   +86     
=======================================
+ Hits        53129    53171   +42     
- Misses      13769    13774    +5     
  Partials        6        6           
Flag Coverage Δ
backend 79.14% <89.85%> (+<0.01%) ⬆️

Flags with carried forward coverage won't be shown. Click here to find out more.

Components Coverage Δ
core 85.27% <ø> (ø)
engine 83.59% <ø> (-0.10%) ⬇️
api 90.14% <89.85%> (+0.16%) ⬆️
nodes 75.38% <ø> (ø)
server 80.26% <ø> (ø)
plugin-native 83.47% <ø> (ø)
plugin-wasm 91.90% <ø> (ø)
ui-services 84.67% <ø> (ø)
ui-components 60.49% <ø> (ø)
Files with missing lines Coverage Δ
crates/api/src/yaml/compiler.rs 96.77% <89.85%> (-0.55%) ⬇️

... and 2 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

streamkit-devin and others added 3 commits May 26, 2026 19:22
- Apply the non-object params rejection in all engine modes, not just
  non-dynamic. Dynamic pipelines now also fail at compile time instead
  of deferring to the node factory.
- Include the node name in the error message for easier debugging with
  multiple mixer nodes.

Signed-off-by: streamkit-devin <devin@streamkit.dev>
- Merge the two adjacent audio::mixer if-blocks into a single branch
  with the mode-gated injection nested inside.
- Add a test pinning the fail-fast behavior for Some(Value::Null) params.

Signed-off-by: streamkit-devin <devin@streamkit.dev>
@streamer45 streamer45 enabled auto-merge (squash) May 27, 2026 21:15
@streamer45 streamer45 merged commit 5d4ae13 into main May 27, 2026
29 checks passed
@streamer45 streamer45 deleted the devin/1779719252-fix-mixer-non-object-params branch May 27, 2026 21:37
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.

yaml/compiler: audio::mixer num_inputs auto-injection silently no-ops on non-object params

2 participants