Ironflow is pre-1.0: APIs can change between releases. Pin a version. What is ready →
- Releases
- Ironflow v0.53.0
Ironflow v0.53.0
Ironflow v0.53.0 fsyncs JetStream on every write, so a crash or power loss cannot roll back an acknowledged write. Runs get slower as a result. An assistant can now list failed runs over MCP, and a failed invoke child now fails its parent run instead of looping. Read the breaking changes before you upgrade: 3 items need action.
Breaking Changes
Section titled “Breaking Changes”- JetStream fsyncs every write before it acknowledges it — The nats-server default acknowledged at once and fsynced every two minutes, so an OS crash or power loss could roll back secrets, config, user KV, cron and debounce state, and pub/sub publishes. The embedded server now sets
sync_interval: always, and so do the Docker Compose files and the Helm chart. A 10-step push run went from 6.2 ms to 17.9 ms on SQLite in a Linux VM. Outbox delivery stays near 610 events/s per node in the VM and drops from about 620 to 160-200 events/s on macOS.spec.nats.syncInterval,--nats-sync-intervalandNATS_SYNC_INTERVALtakealwaysor a positive Go duration; any other value stopsserve. Upgrading: for the old throughput, set--nats-sync-interval=1sor longer and accept that window of loss. With external NATS (--nats-url), addsync_interval: alwaysto thejetstreamblock of each NATS server yourself (ADR 0134, #3205) emit,invoke,stream append,topic publishandevent upcastread stdin only for--data-file -— An open pipe from an agent harness, a CI step orsshused to hang these commands, and an explicit--datafailed with “cannot combine multiple data sources”. Without the flag, a pipe is now ignored with a note on stderr, and a non-empty file redirected to stdin fails instead of sending{}. Upgrading: change... | ironflow emit xto... | ironflow emit x --data-file -, andironflow emit x < payload.jsontoironflow emit x --data-file payload.json(#3201)- An invalid yield from a pull worker fails the run with
YIELD_REJECTED— The REST update answered500and left the runrunningwith its lease held, so a worker that retried the500looped. It now fails the run without a retry, releases the lease and answers400invalid_argument. The streaming worker fails the run the same way. A sleep orwaitForEventyield with an emptystep_idis now an invalid yield in push and pull mode. A store error still answers500and keeps the lease (#3203)
Features
Section titled “Features”- Filters on the MCP tool
ironflow_list_runs—status(comma-separated, such asfailed,paused),function_id,search(pattern match on the run ID),event_id,sinceanduntil(RFC3339) reach the server, so an assistant can list the failed runs. An unknown status, a bad timestamp, a non-string value or a window whereuntilis not aftersinceis refused before any request is sent (#3214, #3215)
- A failed or timed-out invoke child reaches its parent in push mode — The push executor sent only completed steps, so the parent yielded the invoke again in a hot loop and stayed
waiting. Push now sends the failed invoke step, as pull and streaming do, and itserroris the error object as a JSON string. The Go and Python push handlers decode it, soInvokeErrorcarries the child run ID and cause. A failedinvokeAsync, such as an unknown target function, now raisesInvokeErrorin push mode too (#3206) - Go SDK: a failed
Invokechild fails the parent run at once —IsRetryabletreated*InvokeErroras retryable, so the parent satwaitingbetween retries and then paused.*InvokeError, including an invoke timeout, is now non-retryable with codeINVOKE_FAILEDin push, pull and streaming mode, as in the Node and Python SDKs. The parent’s compensations run at once (#3185) - A run whose resumes make no progress fails with
RESUME_NO_PROGRESS— A worker that kept yielding a step the engine had already finished looped at full speed. The run now fails after 10 consecutive resumes from the same step. An operator resume sets the count to zero (#3208) - A repeated yield of a completed sleep or wait step no longer restarts it — The engine keeps the stored step result and resumes the run. A fenced wait re-yield no longer sets the completed step back to waiting (#3212)
- Run search on SQLite treats
\as the escape character —\%and\_in aListRunssearchmatch a literal%or_on SQLite and PostgreSQL. Before,run\_01found nothing on SQLite (#3216) - MCP list tools report bad paging as
invalid_argument— A badlimitoroffsetreportedunknown. A nulllimitoroffsetnow counts as omitted (#3214)