Fix picker dead-end for single-file repos, stale LoRA state after deferred compile, slash upload cap

Tag cached diffusion repos that ship no model_index.json with single_file in the
cached-models listing, and keep them out of the task-scoped On Device pickers
unless the curated catalog carries their artifact: the selection fall-through
loads uncataloged rows as a full pipeline and from_pretrained fails on a
single-file checkpoint repo after the GPU handoff.

Refresh diffusion status after a successful generation run on the Images page.
Speed Auto compiles the transformer on the third LoRA-free generation and flips
supports_lora to false; without the refresh the LoRA picker stayed enabled and
the next LoRA generation failed on the backend.

Match upload passthrough exact paths with trailing slashes normalized: the
trailing-slash variant of /api/train/diffusion/dataset reaches MaxBodyMiddleware
before the router's redirect_slashes 307, so it fell through to the default
/api/train body cap and 413ed large uploads. JSON sub-routes keep extra path
components after normalization and stay on the small cap.
This commit is contained in:
Daniel Han 2026-07-10 08:06:20 +00:00
commit c249d0c50a
7 changed files with 141 additions and 11 deletions

View file

@ -2273,8 +2273,12 @@ export function HubModelPicker({
// Gate on a curated ARTIFACT (artifactForRepoId, what loadSpecFor resolves), not a
// group-key match: a base / uncurated-quant sibling (Qwen/Qwen-Image-2512) matches
// the group by key but has no loadable artifact and dead-ends at the trust gate.
// An unsloth repo must also be a full pipeline (not single_file): the selection
// fall-through loads uncataloged rows as kind "pipeline", and from_pretrained on
// a single-file checkpoint repo (no model_index.json) fails after the handoff.
// Curated single-file artifacts stay: loadSpecFor carries their filename.
(!task ||
isUnslothRepoId(c.repo_id) ||
(isUnslothRepoId(c.repo_id) && !c.single_file) ||
(catalog ? artifactForRepoId(c.repo_id, catalog) !== null : false)),
),
downloadedSort,

View file

@ -326,6 +326,10 @@ export interface CachedModelRepo {
/** True when the snapshot is incomplete (a cancelled/partial download). Such a
* repo must not count as downloaded, or a click re-downloads the full weights. */
partial?: boolean;
/** True for a diffusion repo with no model_index.json: a single-file checkpoint that
* loads only via from_single_file + a checkpoint filename. Task pickers must not offer
* it as a pipeline load unless the curated catalog carries its artifact. */
single_file?: boolean;
}
export async function listCachedModels(

View file

@ -1903,6 +1903,11 @@ export function ImagesPage({ active = true }: { active?: boolean }) {
res.images.forEach((image) => void ensureSrc(image));
setGenDone(i + 1);
}
// A generation can change server-side status: Speed=Auto compiles the
// transformer on the 3rd LoRA-free run (supports_lora flips to false), so
// without a refresh the LoRA picker stays enabled and the next LoRA run
// fails on the backend. Cheap status GET; also picks up any other drift.
if (isMounted.current) void refreshStatus();
} catch (err) {
toast.error(err instanceof Error ? err.message : "Image generation failed");
} finally {
@ -1912,7 +1917,7 @@ export function ImagesPage({ active = true }: { active?: boolean }) {
setGenDone(null);
setGenStep(null);
}
}, [prompt, negativePrompt, width, height, steps, guidance, seed, batchSize, count, workflow, initImage, maskImage, strength, extendPct, extendSides, upscaleFactor, upscaleStrength, referenceImages, loras, controlnetCapable, controlnetId, controlImage, controlType, controlStrength, ensureSrc]);
}, [prompt, negativePrompt, width, height, steps, guidance, seed, batchSize, count, workflow, initImage, maskImage, strength, extendPct, extendSides, upscaleFactor, upscaleStrength, referenceImages, loras, controlnetCapable, controlnetId, controlImage, controlType, controlStrength, ensureSrc, refreshStatus]);
// Keep the active workflow valid for the loaded model: an edit-only model (Qwen-Image-
// Edit) has no Create/Transform tabs, a base model has no Edit tab. Snap to the first