Skip to content

Fix crash on empty flush_volumes (bad lexical cast) - #876

Open
DropDOS wants to merge 1 commit into
Snapmaker:mainfrom
DropDOS:fix/flush-volumes-empty-lexical-cast
Open

DropDOS wants to merge 1 commit into
Snapmaker:mainfrom
DropDOS:fix/flush-volumes-empty-lexical-cast

Conversation

@DropDOS

@DropDOS DropDOS commented Sep 17, 2026

Copy link
Copy Markdown

Fixes the "bad lexical cast: source type value could not be interpreted as target" crash reported in #616.

What is happening: update_selections() and load_selections() parse the printer flush_volumes_matrix and flush_volumes_vector values from app config by splitting on "|" and running each token through boost::lexical_cast. has_printer_setting() returns true even when the stored value is an empty string, so the split gives back a single empty token and lexical_cast throws boost::bad_lexical_cast. Nothing catches it, so the whole preset load aborts.

How you run into it: on a Snapmaker U1, syncing filament from the printer can write empty flush volume values into the active printer combo. After that the app throws the bad lexical cast, and because the corrupt combo is reloaded on the next launch it crashes on startup every time until the config is edited by hand.

The fix: a small parse_flush_volume_list() helper that tolerates an empty string and skips empty or malformed tokens instead of throwing, the same way the flush_multiplier value right below it is already guarded. Valid data parses exactly as before. An empty or corrupt value now keeps the existing defaults instead of taking down the load.

I tested the parsing against an empty string, a normal single filament vector, a full 4x4 flush matrix, an empty middle token, and a malformed token. The old code throws on the empty and malformed inputs, the new code returns identical values for good data and no longer throws.

One note: this stops the crash. It does not address why the sync writes empty flush volumes in the first place (the remap that collapses to zero filaments), which looks like a separate issue worth its own look.

update_selections() and load_selections() read the printer's
flush_volumes_matrix and flush_volumes_vector app-config values by
splitting on '|' and passing every token through boost::lexical_cast<double>.
has_printer_setting() returns true even when the stored value is an empty
string, so the split produces a single empty token and lexical_cast throws
boost::bad_lexical_cast. Nothing catches it, so the whole preset load bails out.

I ran into this on a Snapmaker U1. Syncing filament from the printer can write
empty flush volume values into the active printer combo, and after that the app
throws "bad lexical cast: source type value could not be interpreted as target".
Because the bad combo gets reloaded on the next launch, it then crashes on
startup every time until you hand-edit the config. Same issue as Snapmaker#616.

This adds a small parse_flush_volume_list() helper that skips empty or malformed
tokens instead of throwing, the same way the flush_multiplier value right below
it is already guarded. Valid data parses exactly as before. An empty or corrupt
value now just keeps the existing defaults instead of taking down the load.
@DropDOS

DropDOS commented Sep 17, 2026

Copy link
Copy Markdown
Author

Status update. Confirmed the root cause and reproduced both failure modes on a real U1 this session.

Sync reads a cached filament snapshot and never refreshes it at sync time. Filament presence on this machine comes from per slot motion sensors, so a slot reads empty during a runout or a load, and Orca caches whatever it last saw, sometimes for a long time.

Both failure modes reproduced live:

  1. Crash. Syncing against a stale snapshot where a slot reads empty, on a small project, collapses the filament count to zero, which writes empty flush volumes, which is the bad lexical cast this PR guards against.
  2. Wrong count, no crash. The machine had all four slots loaded, the project had three, sync returned three and dropped the fourth. The overwrite collector sizes its result to the current project count instead of the machine.

This PR is the crash safety layer and stands on its own. Two follow ups are in testing: the collector should return the loaded filaments regardless of project size, and sync should pull a live reading instead of trusting the cache. The logic for both is verified with standalone tests.

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.

1 participant