Relationships
#2575 model delete crashes on unrelated malformed output record (negative durationMs)
Opened by brucejo75 · 9/28/2026· Shipped 9/28/2026
'swamp model delete ' calls modelDeletePreview, which loads ALL output records repo-wide via YamlOutputRepository.findByDefinition -> findAll -> ModelOutput.fromData, rather than scoping the read to the target model's own outputs. If any output record anywhere in .swamp/outputs fails schema validation, delete of ANY model fails, not just the one that produced the bad record.
Reproduced with swamp model delete meris-sdlc-next --force --yes --json,
where the target model (meris-sdlc-next) has zero recorded outputs of its own.
The crash comes from a single unrelated record belonging to a different model:
.swamp/outputs/@swamp/software-factory/approve/8f85198a-475c-4ebd-bff1-bb4a8920b8e0-2026-08-21T21-35-41-471Z.yaml startedAt: 2026-08-21T21:35:41.471Z completedAt: 2026-08-21T21:35:40.636Z (835ms BEFORE startedAt)
ModelOutput.fromData computes durationMs = completedAt - startedAt and validates it as >= 0 via zod, so this record throws:
ZodError: durationMs: Too small: expected number to be >=0
Stack: ModelOutput.fromData (domain/models/model_output.ts:235) YamlOutputRepository.findAll (infrastructure/persistence/yaml_output_repository.ts:179) YamlOutputRepository.findByDefinition (infrastructure/persistence/yaml_output_repository.ts:127) modelDeletePreview (libswamp/models/delete.ts:268) cli/commands/model_delete.ts:152
The negative duration itself is a real artifact of a diagnosed and since-fixed guest-clock issue (timesyncd stepping the clock backward mid-run on a WSL2 host); it's expected that a handful of old records carry it. The bug is that one unrelated, already-understood bad record anywhere in the repo can block deleting an unrelated model.
Suggested fixes:
- Scope findByDefinition's underlying scan to the target definitionId before parsing/validating each record, instead of loading everything via findAll.
- Make ModelOutput.fromData tolerant of a negative computed duration (clamp to 0, or make durationMs optional/nullable) rather than throwing, since clock skew during a run is an environmental fact, not a corrupt record.
Shipped
Click a lifecycle step above to view its details.
stack72 commented 9/28/2026, 1:46:02 PM
Thanks @brucejo75 for reporting this! We shipped: Stop one bad output record from breaking model delete and every other output read. Clamp the derived durationMs to 0 when a run completes, normalize legacy negative durations to 0 when reconstituting records, and make the output repository skip and warn on any record it cannot parse or validate, while I/O errors still propagate.. The fix has been merged and a release is on its way. We appreciate your contribution to swamp.
Sign in to post a ripple.