You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
An empty --to resolves to the first named person instead of failing #30
Context::find_person (src/context.rs) matches names case-insensitively with contains, and
does not reject an empty reference. So an empty string matches the first named person rather
than failing.
In a script, --to "$PERSON" with PERSON unset or empty silently reassigns faces onto whichever
person happens to be listed first, instead of refusing.
The lookup is shared, so this affects people show, people name, people hide, people merge
and now people reassign — including two commands that move data.
Reproduction
imogen people reassign <face-id> --to ""
Observed: faces are moved onto an arbitrary person, exit 0. Expected: a refusal naming the problem.
Expected
find_person bails on an empty or whitespace-only reference before it searches. One reference.trim().is_empty() guard closes it for all five commands at once.
Worth considering at the same time whether a substring match is right for a destructive
operation at all — --to "Al" matching "Alice" is convenient for people show and rather less so
for merge and reassign — but the empty case is the bug and can be fixed on its own.
Affected repos
Only this one. Nothing on the wire changes.
Context
Found by review while implementing #5 (people reassign). Pre-existing; the new command made it
reachable from a data-moving path for the second time.
Context::find_person now bails on an empty or whitespace-only reference before the lookup, so all five commands that share it refuse — and refuse before anything reaches the wire. The reference is trimmed once and searched in its trimmed form, so the guard and the search agree about what is empty.
Reproduced first as a test against a one-person library, which is where the bug was quiet: reassign(…, Some("")) succeeded and moved the faces onto the only person, exit 0.
On the substring question you raised: kept substring matching, and added the exact-name tier find_album already has — but only when exactly one person carries the name. Somebody called "Al" was previously unreachable by their own whole name, since contains matched both "Al" and "Alice" and it was refused as ambiguous; the precise string now wins over a longer one it starts. Because person names are not unique — people merge exists because grouping produces two clusters for one person — two people called "Al" fall through to the ambiguity refusal rather than resolving to whichever the server listed first.
Not done: restricting merge and reassign to exact matches only. A name that works for people show failing on people reassign makes a reference whose meaning depends on the verb, which is harder to reason about than one rule everywhere. Ambiguity is already refused and ids remain the machine path.
Noted in the PR under ## Found, not fixed: find_album has the same empty-reference hole with a worse blast radius (imogen trash --album ""), its exact-name tier is not checked for uniqueness either, and album_or_create matches on Err(_) so an ambiguous name creates a duplicate instead of refusing. Those three want fixing together — guarding find_album alone would make album_or_create start creating an album named "".
Activity
Refuse argument combinations that used to resolve to something arbitr…
ergofobe commentedon Sep 15, 2026
Fixed in #37 (squashed to
main).Context::find_personnow bails on an empty or whitespace-only reference before the lookup, so all five commands that share it refuse — and refuse before anything reaches the wire. The reference is trimmed once and searched in its trimmed form, so the guard and the search agree about what is empty.Reproduced first as a test against a one-person library, which is where the bug was quiet:
reassign(…, Some(""))succeeded and moved the faces onto the only person, exit 0.On the substring question you raised: kept substring matching, and added the exact-name tier
find_albumalready has — but only when exactly one person carries the name. Somebody called "Al" was previously unreachable by their own whole name, sincecontainsmatched both "Al" and "Alice" and it was refused as ambiguous; the precise string now wins over a longer one it starts. Because person names are not unique —people mergeexists because grouping produces two clusters for one person — two people called "Al" fall through to the ambiguity refusal rather than resolving to whichever the server listed first.Not done: restricting
mergeandreassignto exact matches only. A name that works forpeople showfailing onpeople reassignmakes a reference whose meaning depends on the verb, which is harder to reason about than one rule everywhere. Ambiguity is already refused and ids remain the machine path.Noted in the PR under
## Found, not fixed:find_albumhas the same empty-reference hole with a worse blast radius (imogen trash --album ""), its exact-name tier is not checked for uniqueness either, andalbum_or_creatematches onErr(_)so an ambiguous name creates a duplicate instead of refusing. Those three want fixing together — guardingfind_albumalone would makealbum_or_createstart creating an album named"".Refuse an album reference that cannot pick one album (#42)