Skip to content

At-command completion cannot recover from a transient search error while typing #3373

Description

@acoliver

Summary

useAtCompletion has no transition out of its ERROR state on a pattern change. Once an @ completion search fails, continuing to type never retries — the suggestion list stays permanently empty for that working directory until the completion is torn down entirely.

Found while adding completion coverage for #2019. Filing separately because #2019 is a test-only issue and this is a production state-machine fix.

Root cause

usePatternChangeHandler in packages/cli/src/ui/hooks/useAtCompletion.ts only starts work from three statuses:

if (state.status === AtCompletionStatus.IDLE) {
  dispatch({ type: 'INITIALIZE' });
} else if (
  (state.status === AtCompletionStatus.READY ||
    state.status === AtCompletionStatus.SEARCHING) &&
  normalizedPattern !== state.pattern
) {
  ...
}

ERROR is absent, so a new pattern while in ERROR dispatches nothing. The only ways out are RESET, which is reached by disabling the hook, passing a null pattern, or changing cwd/config via useResetOnCwdChange.

Evidence

Probe against the real hook: force FileSearch.initialize to reject once, let the hook settle into the failed state, then change only the pattern (same cwd) to one that would match a real file.

PROBE: entered error state, factory calls = 1
PROBE: after pattern change -> suggestions = [] factoryCalls = 1

No second FileSearchFactory.create, no new search, no suggestions. Changing cwd instead does recover, which is what the existing coverage in useAtCompletion.test.ts exercises.

User-visible effect

If the initial file-system crawl fails once (transient I/O error, permissions hiccup, a directory removed mid-crawl), @ completion appears silently broken for the rest of that session in that directory. Typing more characters looks like it should retry, and does not. The user has to delete the @ entirely and start over, which is not discoverable.

Suggested fix

Allow ERROR to re-enter initialization on a pattern change, so a subsequent attempt retries rather than being dropped. Worth deciding whether every keystroke should retry or whether the retry should be bounded, since a genuinely broken directory would otherwise retry on each character.

Acceptance

A test that drives the hook into ERROR, then changes only the pattern with cwd unchanged, and asserts suggestions populate and isLoadingSuggestions is false. That test fails on main today.

Related

Metadata

Metadata

Assignees

Labels

Ink UIthe packages/cli Ink based UI.

Type

Projects

Status
In Progress

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions