Skip to main content
← Back to list
01Issue
BugShippedSwamp CLIPublic
Assigneesstack72

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:

  1. Scope findByDefinition's underlying scan to the target definitionId before parsing/validating each record, instead of loading everything via findAll.
  2. 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.
02Bog Flow
✓OPEN✓TRIAGED✓IN PROGRESS✓SHIPPED+ 1 MOREASSIGNED+ 5 MOREREVIEW+ 11 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

9/28/2026, 1:45:54 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack729/28/2026, 1:14:32 PM
Editable. Press Enter to edit.

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.