Relationships
#2453 Streamed process output renders curly braces doubled in log output
Opened by stack72 · 9/23/2026
Description
Streamed process output that contains curly braces renders with every brace doubled in log-mode terminal output. The stored data is correct; only the live log line is wrong.
Found while reproducing swamp-club#2397.
Steps to Reproduce
command/shellmodel with method argumentrun: echo '{"a": 1}' >&2(or any command whose stdout/stderr contains braces).swamp model method run <model> execute- The terminal shows the braces doubled, while
swamp data get <model> result --jsonshows them single.
Observed concretely with a shell error message: the terminal line read /bin/sh: ${{{{ 1 + 'a' }}}}: bad substitution while the stored stderr field read /bin/sh: ${{ 1 + 'a' }}: bad substitution.
Cause (suspected)
escapeLogTemplate in src/infrastructure/logging/logger.ts doubles braces so LogTape does not treat them as placeholders, and src/infrastructure/process/process_executor.ts (around lines 198, 203, 334, 339) passes the escaped string to logger.info / logger.warn. The escape is not undone on this rendering path, so the doubled braces reach the terminal. The same helper is used in src/presentation/renderers/issue_create.ts.
Expected Behavior
Process output is rendered verbatim — braces appear once, matching the stored data.
Environment
- swamp 20260923.203315.0-sha.4ae1cfd9
- macOS
Closed
No activity in this phase yet.
stack72 commented 9/23/2026, 10:59:08 PM
Fixed in https://github.com/swamp-club/swamp/pull/2598 (merged), shipped together with swamp-club#2397.
Cause: wrapLoggerWithOutput (src/domain/models/in_process_executor.ts) builds the line shown in the terminal from the raw LogTape template argument. Process output is escaped with escapeLogTemplate ({ becomes {{) so LogTape does not read braces as placeholders. LogTape undoes that for its own sinks, but the wrapper did not, so the doubled braces reached the display. The same applied to extension models logging a plain string containing {{, and to worker-executed models, which use the same wrapper.
Fix: the wrapper now renders string templates the way LogTape does. Doubled braces become single ones, and {key} placeholders are filled only when properties are passed. Single-brace text logged without properties (JSON, for example) is left as written. Tagged templates are unchanged.
Verified on the compiled binary: output containing {"a": 1} shows once in the terminal and matches the stored data, and text that really contains doubled braces displays exactly as written.
Sign in to post a ripple.