Skip to content

fix(cf): register crashes on first name collision under set -e#7

Merged
marksverdhei merged 1 commit into
mainfrom
fix/register-set-e-collision-crash
Jun 27, 2026
Merged

fix(cf): register crashes on first name collision under set -e#7
marksverdhei merged 1 commit into
mainfrom
fix/register-set-e-collision-crash

Conversation

@marksverdhei

Copy link
Copy Markdown
Owner

Bug

cf register's name-retry loop used ((attempts++)):

attempts=0
while [ $attempts -lt 100 ]; do
    ...
    grep -q "^${MYNAME}:" "$CHATFILE" 2>/dev/null || break
    ((attempts++))           # <-- on the 1st iteration this evaluates to 0
done

((expr)) returns exit status 1 when the arithmetic result is 0, and post-increment attempts++ evaluates to the old value (0) on the first iteration. With the script's set -e, that aborts cf register the moment a generated name collides with an existing participant — instead of retrying for a fresh name.

$ bash -c 'set -e; attempts=0; ((attempts++)); echo survived'   # never prints; exit 1

Fix

  • attempts=$((attempts + 1)) — an assignment always returns success, so the loop retries correctly.
  • Added a guard: if all 100 attempts collide, error out instead of silently registering a duplicate name (the old loop fell through using the last colliding name).

Test

test_register_survives_name_collisions fills a chunk of the name space so collisions are frequent, then registers 30×; each must succeed with a non-empty name. It fails against the old ((attempts++)) (39/40) and passes with the fix (40/40).

Context

Salvaged from #1, which I'm closing as superseded: it predates the global-room rework (#3 closed issue #2 with a different $HOME/.cf_session approach) and its diff would revert main's CI workflow and presentation-helper tests. This is the one unambiguous, still-applicable fix from it. (Other candidates in #1send newline sanitization, tail -f orphan cleanup in await, a LASTLINE read-cursor — are noted on #1 as possible follow-ups.)

🤖 Generated with Claude Code

… set -e

`cf register`'s retry loop used `((attempts++))`. Post-increment evaluates to
the *old* value, so on the first iteration it yields 0 — which bash reports as
exit status 1. Combined with the script's `set -e`, that aborted `cf register`
entirely the moment a generated name collided with an existing one, instead of
retrying. Replace it with `attempts=$((attempts + 1))` (an assignment always
returns success), and add a guard so exhausting all 100 attempts errors out
rather than silently registering a duplicate name.

Adds a regression test (`test_register_survives_name_collisions`) that fills a
chunk of the name space so collisions are frequent and registers 30×; it fails
against the old `((attempts++))` and passes with the fix. Suite: 40/40.

Salvaged from the superseded #1 (which can't merge — it predates the global-room
rework and would revert main's CI + presentation tests).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@marksverdhei marksverdhei merged commit bbd4aac into main Jun 27, 2026
1 check passed
@marksverdhei marksverdhei deleted the fix/register-set-e-collision-crash branch June 27, 2026 16:03
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.

1 participant