Skip to content

High: [Containers] Mixer.balances_solids Cake branch leaves Outlet and distrib unset #88

Description

@sergey-gusev94

Maintainer triage (June 29, 2026)

  • Status: Verified bug against the current master source in this fork.
  • Severity: High.
  • Area labels: area:containers.
  • Tackle batch: P3 - documented-mode crashes and tooling breakages.

The source review confirmed that the cited code path and failure mode are still present. The original audit details are preserved below for reproduction notes and suggested fixes.


Original audit details

Severity: High · Part of #67 (round-2 audit batch)

Cake branch leaves self.Outlet and distrib unbound, then unconditionally calls energy_balance and returns distrib

Location: PharmaPy/Containers.py:500-507 (also 505, 580, 595)

The slurry-vs-cake split at line 476 (if vol_liq > vol_pores) only fully populates the Slurry branch (476-499 sets self.Outlet at 482/497, self.Outlet.Phases at 499, and local distrib at 479). The else/Cake branch (500-502) is a stub: self.type_out = 'Cake' then 'pass # TODO: create Cake object' -- it never assigns self.Outlet or distrib. Execution unconditionally reaches line 505 temp_out = self.energy_balance(u_inputs), and energy_balance (360-361) calls self.Outlet.getEnthalpy(temp) inside temp_root via newton -> AttributeError ('Mixer' has no attribute 'Outlet'; Mixer.init never sets it). Even if bypassed, line 507 returns the unbound local distrib -> UnboundLocalError. retrieve_results (582-585) explicitly branches on type_out=='Cake' and line 595 calls self.Outlet.Solid_1.updatePhase(...), confirming Cake is an intended mode.

  • Trigger: A Mixer fed at least one MixedPhases (Slurry/Cake) inlet plus enough solid / little enough liquid that vol_liq <= vol_pores (the physically correct wet-cake outcome). solve_unit -> balances_solids takes the else branch at line 500. balances_solids runs when an inlet is MixedPhases and mass_frac is not a list (the non-timeseries batch path).
  • Wrong result: AttributeError (self.Outlet has no getEnthalpy) at line 505 via energy_balance, or UnboundLocalError on distrib at line 507. The mixer is unrunnable for any solids mix that yields a cake, despite retrieve_results being written to handle type_out=='Cake'.
  • Suggested fix: Implement the Cake branch: build a Cake/Outlet object and assign distrib before line 505 (e.g. distrib = distrib_in.sum(axis=0) and self.Outlet = Cake with the liquid/solid phases). If cake output is not yet supported, raise an explicit NotImplementedError in the else branch instead of 'pass', and guard energy_balance/the return so they are not reached with an unset Outlet.
  • Net-new (not a duplicate): Not High: [Containers] Mixer slurry energy balance weights liquid enthalpy by total slurry Cp #25 (liquid-only mass weighting, assumes the slurry path), not Medium: [Containers] Mixer energy balance uses inconsistent inlet and outlet enthalpy references #38 (reference-temperature in Mixer.balances/dynamic_balances), not High: [Containers] DynamicCollector corrupts result ordering and has dead crystallizer plotting branch #75 (DynamicCollector). Distinct unbound-name/unset-Outlet crash in Mixer.balances_solids' Cake branch.

Related existing issues (referenced, not modified): #25 (Mixer slurry liquid-only mass weighting), #38 (Mixer reference-temperature mismatch), #75 (DynamicCollector) -- reference only; none cover the Cake-branch crash.


Found by a multi-agent source audit (round 2); confirmed by re-reading the source and cross-checked against all 80 existing open issues. Each defect was verified by an independent code-truth skeptic and a novelty skeptic.

Metadata

Metadata

Assignees

Labels

area:containersMixer, collector, holdup, and container unit operationsbugSomething isn't workingcorrectnessModel/numerical correctness defectseverity:highConfirmed bug with major correctness impact or broken documented workflowstatus:verifiedSource-reviewed against the current codebase

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions