Skip to content

fix(record): guard empty ${adb_args[@]} so device_record stop survives macOS bash 3.2 (#374)#375

Merged
Lykhoyda merged 1 commit into
mainfrom
fix/374-record-proof-adb-args-unbound
Jul 1, 2026
Merged

fix(record): guard empty ${adb_args[@]} so device_record stop survives macOS bash 3.2 (#374)#375
Lykhoyda merged 1 commit into
mainfrom
fix/374-record-proof-adb-args-unbound

Conversation

@Lykhoyda

@Lykhoyda Lykhoyda commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Fixes #374.

What

device_record action=stop aborted on macOS with:

record_proof.sh: line 180: adb_args[@]: unbound variable

cmd_stop's Android branch declares local -a adb_args=() and only fills it when a .serial sidecar exists. In the single-device case cmd_start rm's that sidecar, so adb_args stays empty — and under set -euo pipefail on bash 3.2 (the macOS default /bin/bash) expanding an empty array as "${adb_args[@]}" is an unbound-variable error, aborting the stop before the pull/convert. Because cmd_stop loops over all ${PID_PREFIX}-*.pid sidecars, a leftover Android .pid made even iOS stops crash.

Bash ≥ 4.4 removed that behavior, so it never reproduced on ubuntu-latest CI — which is why the full unit suite never caught it.

Fix

Apply the +-default guard already used in the same file (saved_paths at what was line 249) to the three adb_args expansions:

adb "${adb_args[@]+"${adb_args[@]}"}"

+3 −3 in scripts/record_proof.sh.

Tests (gh-374-record-proof-adb-args-unbound.test.js)

Two layers, because the runtime crash is bash-version-specific:

  1. Static invariant (CI-effective on bash 5.x): asserts no unguarded adb "${adb_args[@]}" remains and the 3 guarded forms are present. Verified it flips to fail when the guard is reverted.
  2. Behavioral reproduction (gated to bash < 4.4 / macOS): seeds a serial-less single-device Android stop state in a hermetic temp prefix, asserts an intentionally-unpatched copy does crash (proving the test detects the bug) and the real patched script does not.
  • Full suite: 2539 passing (added 2).
  • oxlint + oxfmt --check: clean.

Device-verified

Found while device-verifying #282 on a live Android emulator + iOS sim. After the fix, Android stop finalized a 38 s MP4 where it crashed twice before; iOS unaffected. (The #282 investigation separately confirmed #282 was already mitigated — closed as such.)

🤖 Generated with Claude Code

…vives on macOS bash 3.2 (#374)

record_proof.sh cmd_stop expanded an empty `adb_args` array unguarded in the
Android branch; under `set -euo pipefail` on bash 3.2 (the macOS default
/bin/bash) that aborts with `adb_args[@]: unbound variable` before the
pull/convert, breaking recording finalize — and a leftover Android .pid made
even iOS stops crash. Apply the `+`-default guard already used at the
saved_paths site to all three expansions.

Regression-guarded by a static invariant test (CI-effective on bash 5.x) plus
a behavioral reproduction gated to bash < 4.4. Found while device-verifying #282.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Lykhoyda Lykhoyda merged commit a6112e6 into main Jul 1, 2026
11 checks passed
@Lykhoyda Lykhoyda deleted the fix/374-record-proof-adb-args-unbound branch July 1, 2026 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: device_record stop crashes on macOS (bash 3.2) — unguarded ${adb_args[@]} empty-array expansion under set -u

1 participant