ObjectManager._upload_action_async is the single entry for every action path (setters, direct edits of the public action array, run()). It now also rejects nonzero vx/vy/omega slots of Jet-driven bodies via validate_jet_motion, before any device copy. Regression: each motion slot edited directly is rejected with no device write; zero motion uploads. Simulation.set_jet_amplitude documents that a device error requires close/recreate, as for other CUDA exceptions. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>