Skip to main content
← Back to list
01Issue
BugShippedSwamp CLIPublic
Assigneesskunk-ape

Relationships

#3006 vault read-secret: to a pipe or file, drops the last line of a multi-line value when that line is 1024+ chars with no trailing newline (exit 0)

Opened by randybias · 10/4/2026· Shipped 10/5/2026

Summary

swamp vault read-secret <vault> <key>, with stdout NOT a terminal (pipe or file), drops the LAST line of a multi-line value when that line is 1024 characters or longer and has no trailing newline. Exit status is 0, and nothing goes to stderr. The value is stored whole: --json and terminal output return all of it. A script that builds a file from the plain output (for example a kubeconfig, where client-key-data is the last line) gets a broken file and no error.

Version

swamp 20260929.002922.0-sha.55e2ef29, Linux x86_64, local_encryption vault. We saw it first on a sops-age vault (@zocc/sops-age) with a kubeconfig: 3445 of 5707 bytes returned, last line 2261 chars.

Minimal reproduction (throwaway repo)

swamp repo init && swamp vault create local_encryption tv
for n in 1020 1021 1500; do
  python3 -c "import sys;sys.stdout.write('a: b\nk: '+'x'*$n)" > c_$n   # last line = n+3 chars, no trailing newline
  swamp vault put tv t$n --force < c_$n
  echo "n=$n file=$(wc -c < c_$n) read=$(swamp vault read-secret tv t$n --yes --quiet | wc -c)"
done

Measured:

last line trailing \n stored (bytes) read-secret to a pipe --json value terminal (script -qc)
1023 chars no 1028 1028 OK - -
1024 chars no 1029 5 (first line only) - -
1503 chars no 1508 5 1508 OK 1508 + newline OK
2264 chars yes 2307 2307 OK - -
single line, 3000 chars no 3000 3000 OK - -

The same happens without --quiet, and with output redirected to a file (> out: 5 bytes, empty stderr).

Source

src/presentation/renderers/vault_read_secret.ts:41-46 (same at 55e2ef29 and main bed0772a): a terminal gets writeOutput(value) (console.log), which works. A non-terminal gets Deno.stdout.writeSync(encoder.encode(value)), which loses the line. writeSync returns the number of bytes written and may write only part of the buffer, and the return value is not checked. I did not find why the cut falls exactly at the last line.

Expected

The full value on every output path, or a non-zero exit if the write is short. Suggested: loop until every byte is written (writeAllSync-style).

Workaround

Read with --json and extract .value.

02Bog Flow
✓OPEN✓TRIAGED✓IN PROGRESS✓SHIPPED+ 1 MOREASSIGNED+ 2 MOREREVIEW+ 7 MOREPR_MERGED+ 2 MORESESSION_SUMMARIZED

Shipped

10/5/2026, 2:05:23 PM

Click a lifecycle step above to view its details.

03Sludge Pulse
skunk-ape assigned skunk-ape10/5/2026, 12:44:23 PM
Editable. Press Enter to edit.

skunk-ape commented 10/5/2026, 2:05:28 PM

Thanks @randybias for reporting this! We shipped: Make the piped and file-redirected output of swamp vault read-secret write the whole secret. The non-terminal path calls Deno.stdout.writeSync once and ignores the returned byte count; Deno's line-buffered stdout writer returns a short count when the trailing partial line is 1024+ bytes, so the last line is dropped with exit 0. Loop until every byte is written, fail loudly on a zero-byte write, add renderer unit tests with a short-writing mock, and prove it end to end with the filed swamp-uat#521 test against the compiled binary.. The fix has been merged and a release is on its way. We appreciate your contribution to swamp.

Sign in to post a ripple.