Maxi
Member
- Messages
- 197
- Reaction score
- 146
(post mostly written by claude, verified be me)
Game Version
v2026.11.10.5801 (reproduced with stock parts only); first found on v2026.10.25.5707
Operating System
Windows 11
What Happened
When the eccentricity of a vehicle orbit lies in the band 1 - 1e-6 <= e < 1, the game throws an exception in the frame update. Stack on v2026.11.10.5801:
In the played game the next frames are
I first saw it in an automated run of a lunar capture burn. The probe came in on a hyperbolic orbit (e = 1.005 at t = 858 s), and the burn pushed it toward a bound orbit. In the next steps the eccentricity landed in the band just below 1, and the exception was thrown. It happened on every run with the same approach speed and never with a slightly different one, because the band is narrow. Per crossing the chance to hit it is small (one physics step of this burn changes e by about 1e-4, and the band is 1e-6 wide). So it will be rare but real for a player who does a long capture burn or slowly circularises an escape orbit.
Reproduction on v2026.11.10.5801
A stock probe core (
What Was Expected
An orbit with e very close to 1 is handled as a parabolic orbit (no period, the next periapsis time is the periapsis time), and no exception is thrown.
Reproduction Steps
Always for e = 0.9999995 with the Set Orbit path. For a burn it is always for a given trajectory in a deterministic run, and in normal play it depends on a step that ends in the band, which is 1e-6 wide.
Additional Info
Found with mods loaded, while I tested my own part mods with automated flight tests, and reproduced on v2026.11.10.5801 with stock parts only (see above). Related reports for other NaN paths near e = 1: "Crash when orbit is near to eccentricity 1" (thread 983,
The exception is not caught on this path: there is no try/catch around
Technical analysis (decompiled 2026.10.25.5707, unchanged in 2026.11.10.5801: Orbit.cs and OrbitData.cs did not change)
Two different tests decide what an orbit is:
Suggested fix
Use the class test instead of the eccentricity test where a period is needed:
Game Version
v2026.11.10.5801 (reproduced with stock parts only); first found on v2026.10.25.5707
Operating System
Windows 11
What Happened
When the eccentricity of a vehicle orbit lies in the band 1 - 1e-6 <= e < 1, the game throws an exception in the frame update. Stack on v2026.11.10.5801:
Code
System.ArgumentException: Cannot construct a UniverseTime from NaN
at KSA.UniverseTime.NanosecondsFromSeconds(Double seconds)
at KSA.UniverseTime.op_Subtraction(UniverseTime a, Double b)
at KSA.Orbit.GetTimeFromToTrueAnomalyAtGameTime(TrueAnomaly tA, UniverseTime gameTime, Boolean suppressWarnings)
at KSA.Orbit.TimeOfTrueAnomaly(TrueAnomaly tA, UniverseTime gameTime, Boolean suppressWarnings)
at KSA.Orbit.GetNextPeriapsisTime(UniverseTime gameTime)
at KSA.Vehicle.UpdatePerFrameData()
at KSA.IParentBody.UpdatePerFrameDataTree()
at KSA.IParentBody.UpdatePerFrameDataTree()
at KSA.CelestialSystem.UpdatePerFrameData()
at KSA.Universe.ApplyVehicleSolvers()
Program.PrepareFrame and Program.OnFrame. On v2026.10.25.5707 the stack was the same, without the two IParentBody.UpdatePerFrameDataTree frames.I first saw it in an automated run of a lunar capture burn. The probe came in on a hyperbolic orbit (e = 1.005 at t = 858 s), and the burn pushed it toward a bound orbit. In the next steps the eccentricity landed in the band just below 1, and the exception was thrown. It happened on every run with the same approach speed and never with a slightly different one, because the band is narrow. Per crossing the chance to hit it is small (one physics step of this burn changes e by about 1e-4, and the band is 1e-6 wide). So it will be rare but real for a player who does a long capture burn or slowly circularises an escape orbit.
Reproduction on v2026.11.10.5801
A stock probe core (
CoreCommandC_Prefab_ProbeCoreSmallA) in a 300 km circular Earth orbit. Then its orbit was set the same way the Set Orbit debug window does it (Vehicle.DrawSetOrbitDebugWindow: new OrbitData(timeAtPeriapsis, parent.Mass, periapsis, eccentricity, inclination, node, argument), then Orbit.Create without state vectors, then a TeleportInputData in InputEvents.TeleportInputBuffer, which Vehicle.Teleport applies). Periapsis 300 km above the atmosphere, inclination, node and argument 0. After that the universe was stepped at 0.02 s per frame:- e = 0.99999 (control):
Orbit.Elliptical, period 1.78e11 s, no exception in 50 frames. - e = 1.0000005 (control):
Orbit.Parabolic,PeriodNaN,Eccentricity < 1.0false, no exception in 50 frames. - e = 0.9999995:
OrbitDatagivesSemiMajorAxis+Infinity,PeriodNaN andApoapsisNaN,Orbit.CreategivesOrbit.ParabolicwithEccentricity0.9999995 (Eccentricity < 1.0true,IsBound()false). The exception above is thrown in the first frame after the teleport. A direct call ofOrbit.GetNextPeriapsisTimeon this orbit throws the same exception.
Vehicle.Teleport cannot run its last line Program.Instance.SchedulePlanetUpdate, because there is no renderer. That line schedules a planet update and comes after the orbit change.What Was Expected
An orbit with e very close to 1 is handled as a parabolic orbit (no period, the next periapsis time is the periapsis time), and no exception is thrown.
Reproduction Steps
- Set Orbit debug tool: fly any vehicle, open Debug > Show Set Orbit Debug, choose Earth as Destination Body, leave Height Options on Periapsis and Offset on Above Atmosphere, enter 300000 as Height, enter 0.9999995 as Eccentricity, and click Set Orbit. The exception is expected in the next frame.
- Capture burn that crosses e = 1 slowly from the hyperbolic side: fly a vehicle on a hyperbolic orbit around a body and burn retrograde at periapsis with a low thrust or at a low time warp, so that e falls from above 1 to below 1 in many small steps. The exception appears when one step ends with 1 - 1e-6 <= e < 1.
Always for e = 0.9999995 with the Set Orbit path. For a burn it is always for a given trajectory in a deterministic run, and in normal play it depends on a step that ends in the band, which is 1e-6 wide.
Additional Info
Found with mods loaded, while I tested my own part mods with automated flight tests, and reproduced on v2026.11.10.5801 with stock parts only (see above). Related reports for other NaN paths near e = 1: "Crash when orbit is near to eccentricity 1" (thread 983,
Orbit.CreateFromStateCci with e slightly above 1, marked as fixed in June) and "Crash while moving BURN panel in map view, UniverseTime from NaN, Burn.PlusClicked" (thread 1280). The stack of this report is different from both.The exception is not caught on this path: there is no try/catch around
Universe.ApplyVehicleSolvers in Program.PrepareFrame or around PrepareFrame in Program.OnFrame, and other reports with the same top-level frames (for example thread 983) show "Unhandled exception" and the game ending. So a played game would stop, not only log a warning.Technical analysis (decompiled 2026.10.25.5707, unchanged in 2026.11.10.5801: Orbit.cs and OrbitData.cs did not change)
Two different tests decide what an orbit is:
OrbitData.IsParabolic()(andOrbit.IsParabolic(double eccentricity)) testMath.Abs(Eccentricity - 1.0) <= 1E-06. In theOrbitDataconstructor (elements version) the parabolic case setsSemiMajorAxis = double.PositiveInfinity,Period = double.NaNandApoapsis = double.NaN.Orbit.Createthen picks the class from the semi-major axis when it has no state vectors (Orbit.IsParabolic(semiMajorAxis, mu)is true for +Infinity), or from the energies when it has state vectors (Orbit.GetOrbitType(orbitalEnergy, potentialEnergy), tolerance1E-06 * (orbitalEnergy + 2 * potentialEnergy)). Both giveOrbit.Parabolicfor this orbit. The energy test is a little wider than the eccentricity test, so a few orbits areParabolicwith a normal period, but the whole band 1 - 1e-6 <= e < 1 is both.
Orbit.Parabolic can have Eccentricity < 1.0 (below 1 by less than 1e-6) and a NaN Period. Several methods use Eccentricity < 1.0 as the test for "bound orbit with a period":Orbit.GetNextPeriapsisTimeandOrbit.GetNextApoapsisTime:if (Eccentricity < 1.0) return TimeOfTrueAnomaly(...).Orbit.GetTimeFromToTrueAnomalyAtGameTime: after it computesvalue = timeFromPeTo - timeSincePeriapsisThisOrbit, it doesif (Eccentricity < 1.0) value -= Period * Math.Floor(value.Seconds() / Period + 0.5);. WithPeriod = NaNthe subtraction goes toUniverseTime.operator -(UniverseTime, double)andUniverseTime.NanosecondsFromSeconds, which throws on NaN.
Orbit.GetTimeSincePeriapsisThisOrbit is safe, because it tests IsBound() (this is Bound), not the eccentricity. Vehicle.UpdatePerFrameData calls GetNextPeriapsisTime and GetNextApoapsisTime for every vehicle every frame, so the exception is thrown in the first frame in which the orbit is in the band. For e >= 1 the same methods take the other branch (TimeAtPeriapsis, gameTime), so only the side below 1 is affected. The two control runs above show both sides.Suggested fix
Use the class test instead of the eccentricity test where a period is needed:
- In
Orbit.GetNextPeriapsisTime,Orbit.GetNextApoapsisTimeandOrbit.GetTimeFromToTrueAnomalyAtGameTime, replaceEccentricity < 1.0byIsBound()(ordouble.IsFinite(Period)). Then anOrbit.Parabolictakes the unbound branch, as an orbit with e >= 1 does today. - Optional: use one classification everywhere. Today
OrbitData.IsParabolic(1e-6 on e),Orbit.IsParabolic(double)(the same) andOrbit.GetOrbitType(energy tolerance) disagree in a thin zone. A shared helper would prevent the next case of this kind, and it would also make it impossible to confuse aParabolicorbit with e < 1 with a bound orbit. - A cheap safety net would be a guard in
Vehicle.UpdatePerFrameDatathat keeps the old_nextPeriapsisTimeand logs a warning instead of letting an exception reach the main loop.
Upvote
0