← Blog

PrintStash v0.12.0: material-aware dispatch, safer first run

Preflight compares material and nozzle before a send. Fleet batches gain copies and release gates. Startup no longer deletes unindexed files. API ships lite.

release

v0.12.0 adds material-aware dispatch to the fleet queue, splits the API into full and lite images, and removes a startup behavior that could delete files PrintStash did not put there. It carries additive database migrations along with deployment and dependency changes, so back up before upgrading, and read the upgrade notes first if you run PostgreSQL, MinIO, or the light Compose file.

The queue now checks the file against the machine

Until this release, routing counted work and nothing else. Nothing stopped an ABS slice from landing on a printer loaded with PLA, or a 0.4 mm file from going to the machine wearing a 0.6 mm nozzle. That was the honest answer to the most common question about the fleet queue, and it is no longer the answer.

Printer tools and material feeds now track where their information came from, and two of those sources can keep themselves current: Bambu AMS state and Moonraker’s active Spoolman spool can synchronize automatically. A G-code preflight then compares the material and nozzle metadata parsed out of the file against what the target machine reports before a direct send goes out.

A mismatch is not a hard block. You can override it, and the override is audited rather than silent, which is the right shape for a farm where the operator sometimes knows better than the metadata.

Fleet batches grew up alongside it. A batch can carry a copy count instead of queueing the same job six times by hand, constrain itself to a printer group, and sit in a priority lane. An optional operator release gate holds dispatch until a person says go, and a printer board gives the fleet an at-a-glance view.

Startup no longer deletes files it does not recognize

This is the entry to read twice if you pointed PrintStash at a folder that already had things in it.

Startup and hourly maintenance used to infer file ownership and recursively delete unindexed objects from configured storage. They no longer do. First-run local vault paths now have to be writable, dedicated, empty directories, failed uploads clean up only their exact destinations, and an occupied path is never overwritten. An existing NAS or Nextcloud folder belongs under External Libraries, where PrintStash indexes bytes in place and never owns them.

If your vault path is currently a shared folder with other files in it, sort that out as part of this upgrade rather than after it.

Two API images

The API now ships as printstash-api and printstash-api-lite. Lite drops Chromium and OpenCASCADE, which means no browser-assisted imports and no STEP tessellation, and keeps mesh thumbnail generation through NumPy, Pillow, and Trimesh. It is more than 700 MiB smaller than the full image, which matters on a Raspberry Pi or any host where pulling the full image is the slow part of an upgrade.

Both images report what they can actually do through authenticated health details, so a client can ask rather than assume. The light Compose file now pulls lite; the default stack still pulls full.

Storage, passwords, and dependencies

The normal Compose stack no longer contains MinIO. SeaweedFS stays as the bundled S3-compatible service, external MinIO endpoints keep working, and a transitional helper copies objects from a MinIO volume without deleting the source, verifying what it downloaded with a digest-pinned rclone image. That helper is temporary and goes away before 1.0.

New password hashes use Argon2. A successful login upgrades a legacy bcrypt hash in place, so nobody needs a password reset, and bcrypt’s historical 72-byte behavior is preserved only for verifying old hashes. Long, Unicode, and malformed passwords, along with damaged legacy hashes, now fail through controlled paths.

Under the hood: PostgreSQL moved to Psycopg 3, mesh processing to NumPy 2 and Trimesh 5, and STEP support is in both amd64 and arm64 full images. aiosqlite is now an opt-in extra. STEP tessellation runs in a disposable child process with a memory budget and a timeout, so a pathological file degrades instead of taking the API down with it.

Imports that tell the truth about themselves

Import jobs publish durable completion metadata, an explicit complete or partial outcome, thumbnail status with stable reasons, and monotonic progress that survives a restart. A job cannot report completion until its model, artifact, metadata, primary storage, and expected thumbnails are visible from a fresh session, which closes the gap where an import looked finished and was not.

Task Center is now the single owner of those transitions, emits one terminal event per job, rejects stale polling responses, and resumes after a reload or a connectivity blip.

Oversized meshes get a memory-bounded streaming STL fallback that produces a 640 by 480 WebP thumbnail, including from Vault Maintenance repair and bulk upload, so a large valid STL no longer finishes silently without a preview.

Smaller things

Bambu LAN beta records prints started outside PrintStash using the identity fields the printer reports, and makes a best-effort grab of the exact G-code or project file while it is still in the printer’s FTPS cache, labelling history as metadata-only when no artifact could be recovered. Preview settings control 3D and G-code render sharpness, downloaded screenshot resolution, and generated model image resolution, with a background action to recreate existing previews. OIDC now accepts issuer URLs differing only by a trailing slash, which fixes Authentik PER_PROVIDER setups while still rejecting genuinely mismatched issuers. Vault Maintenance reports severity totals from the findings it actually returns and skips missing-file checks on trashed items.

Upgrading follows the normal Docker Compose flow. Back up first, then work through the upgrade guide, and check the compatibility matrix for what each printer provider does in the release you are running.