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

Relationships

#974 swamp serve scheduled execution runs steps in an isolated data scope: readResource sees empty state, writeResource never reaches the model-scope chain — stateful scheduled workflows duplicate instead of deduplicating

Opened by magistr · 7/5/2026· Shipped 7/6/2026

Summary

A scheduled workflow on swamp serve executes and delivers correctly per-run, but the step's data scope is isolated per run: context.readResource(...) returns null/empty every scheduled run (it sees neither previous scheduled runs' writes nor CLI-run writes on the model-scope chain), and context.writeResource(...) outputs never become visible on the model-scope chain that swamp data get <model> <name> and subsequent runs' readResource resolve. The SAME workflow via in-container CLI (docker exec swamp-serve swamp workflow run <wf>) has normal semantics. Related but distinct from #914 (sensitive-resource reads in served execution): here NON-sensitive resources, both directions.

(Edit: the originally filed version of this report also claimed the method's Deno.Command("swamp", ...) notification subprocess fails silently — that was wrong; deliveries DO reach Telegram from scheduled runs. Corrected here and in the first ripple; the data-scope isolation is the whole defect.)

Environment

  • swamp serve container (debian:stable-slim + install.sh stable), --repo-dir /workspace, workdir /workspace, @keeb/mongodb-datastore + @webframp/hashicorp-vault
  • Model: @anilist/api v2026.07.04.1 method recent-activity — dedupe cursor via context.readResource("activity-cursor"), writes activityFeed + activityCursor, sends Telegram via a swamp model method run <tg-model> sendMessage --stdin subprocess and only advances the cursor on confirmed delivery
  • Workflow: single model_method step, trigger.schedule: "7 * * * *", lookbackMinutes 120

Observed

  • Scheduler fires hourly, every run reports completed.
  • Model-scope artifacts are FROZEN across 19 scheduled runs: swamp data get my-anilist current / activity-cursor stay at the version written by the last CLI run; checkedAt and the cursor floors never advance. Since the method's writeResource executes without error (a throw would fail the run), the writes must land in a scope invisible to model-scope reads.
  • The runs DO deliver: a scheduled run at 13:07Z posted a single-item digest whose content proves it computed with an EMPTY cursor and a fresh 2h lookback window (11:07–13:07Z). Had it read the model-scope cursor (last advanced by a CLI run a day earlier), its window would have included three additional older undelivered items — it posted only the one item inside the fresh window.
  • Consequence: with lookback (2h) > cadence (1h), every activity is delivered by every scheduled run whose window covers it → systematic duplicates; and delivery-failure retry semantics (cursor hold) can never work because no state survives to the next run.
  • Separate retrieval oddity, still unexplained: in-container swamp data list --workflow <wf> attributes an unrelated model's months-old 86B artifact to the step, data get --workflow <wf> current returns that foreign artifact, and swamp data query 'tags.workflow == "<wf>"' / 'tags.workflowRunId == "<id>"' return "No matching data found" even though artifacts fetched by plain data get carry exactly those tags (Mongo datastore).
  • docker exec swamp-serve swamp workflow run <wf>: normal semantics — writeResource becomes the next model-scope version, the next run's readResource sees it, dedupe cursor works.

Expected

Served scheduled execution should have the same data semantics as CLI workflow execution: step writeResource becomes the next model-scope version (or at minimum, readResource resolves what the previous scheduled run wrote). If per-run isolation is intended, it needs to be documented and a supported mechanism provided for methods that keep dedupe/cursor state across scheduled runs.

Impact / workaround

Any stateful scheduled workflow (notification dedupe, incremental sync cursors, rate-limit bookkeeping) silently degrades on serve: duplicates instead of dedup, no catch-up after downtime. Workarounds: (a) size the lookback window exactly to the schedule cadence and accept lost items on failure windows, or (b) drop trigger.schedule and drive the workflow from host cron via docker exec swamp-serve swamp workflow run <wf> (same class of workaround as #914).

02Bog Flow
OPENTRIAGEDIN PROGRESSSHIPPED+ 1 MOREASSIGNED+ 5 MOREREVIEW+ 4 MOREPR_MERGED+ 1 MORECONTRIBUTOR_NOTIFIED

Shipped

7/6/2026, 4:06:31 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
stack72 assigned stack727/6/2026, 1:33:50 AM
Editable. Press Enter to edit.

magistr commented 7/5/2026, 2:03:00 PM

Correction to the original report after more evidence: the Telegram-send subprocess does NOT fail in served scheduled execution — deliveries DO reach the chat. The defect is narrower and is the state scoping alone:

  • Scheduled-run readResource gets empty/run-scoped state each run (it never sees prior runs' writes, nor CLI-run writes on the model-scope chain), and its writeResource outputs never become visible on the model-scope chain.
  • Consequence for any cursor/dedupe-style method: every scheduled run starts from a fresh window, so the same item is delivered by every run whose window covers it (with an hourly schedule and a 2h lookback, roughly every item twice).

Observed sequence: a subscriber received a single-item digest at 13:07Z posted by the scheduled run (its 2h window contained exactly that one item), while swamp data get <model> current stayed frozen at the version written by the last CLI run, and the method's cursor floors never advanced. In-container CLI runs of the same workflow read/write the model-scope chain correctly.

So: title's "subprocess fails silently" is wrong, please read this as "served scheduled execution uses an isolated data scope for both reads and writes → stateful scheduled workflows duplicate instead of deduplicate". The data list/get/query --workflow mismatches from the original report still stand.

stack72 commented 7/6/2026, 4:06:50 PM

Thanks @magistr for reporting this! The fix has been merged and a release is on its way. We appreciate your contribution to swamp.

Sign in to post a ripple.