DrKLO/Telegram · error · IllegalArgumentException

Invalid direction: {direction}

Error message

Invalid direction: {direction}

What it means

RecyclerView's internal focus-search helper resolves whether a candidate is 'closer' in a given focus direction. Its switch covers FOCUS_LEFT/RIGHT/UP/DOWN/FORWARD/BACKWARD; any other direction constant throws 'Invalid direction'. The focus machinery cannot rank candidates for an axis-less direction.

Source

Thrown at TMessagesProj/src/main/java/androidx/recyclerview/widget/RecyclerView.java:2895

                || mTempRect.top >= mTempRect2.bottom)
                && mTempRect.top > mTempRect2.top) {
            downness = -1;
        }
        switch (direction) {
            case View.FOCUS_LEFT:
                return rightness < 0;
            case View.FOCUS_RIGHT:
                return rightness > 0;
            case View.FOCUS_UP:
                return downness < 0;
            case View.FOCUS_DOWN:
                return downness > 0;
            case View.FOCUS_FORWARD:
                return downness > 0 || (downness == 0 && rightness * rtl > 0);
            case View.FOCUS_BACKWARD:
                return downness < 0 || (downness == 0 && rightness * rtl < 0);
        }
        throw new IllegalArgumentException("Invalid direction: " + direction + exceptionLabel());
    }

    @Override
    public void requestChildFocus(View child, View focused) {
        if (!mLayout.onRequestChildFocus(this, mState, child, focused) && focused != null) {
            requestChildOnScreen(child, focused);
        }
        super.requestChildFocus(child, focused);
    }

    /**
     * Requests that the given child of the RecyclerView be positioned onto the screen. This method
     * can be called for both unfocusable and focusable child views. For unfocusable child views,
     * the {@param focused} parameter passed is null, whereas for a focusable child, this parameter
     * indicates the actual descendant view within this child view that holds the focus.
     * @param child The child view of this RecyclerView that wants to come onto the screen.
     * @param focused The descendant view that actually has the focus if child is focusable, null
     *                otherwise.

View on GitHub (pinned to 45ab8f4308)

Solutions

  1. Use only View.FOCUS_LEFT, FOCUS_RIGHT, FOCUS_UP, FOCUS_DOWN, FOCUS_FORWARD, FOCUS_BACKWARD.
  2. Validate the direction against the set of known constants before invoking focus search.
  3. If you only need nearest-neighbor focus, rely on the default arrow-key handling instead of custom direction injection.

Example fix

// before
recyclerView.focusSearch(focusedView, myCustomDir); // e.g. 0

// after
int dir = View.FOCUS_FORWARD; // one of the six valid constants
recyclerView.focusSearch(focusedView, dir);
Defensive patterns

Strategy: validation

Validate before calling

static boolean isValidFocusDirection(int dir) {
    return dir == View.FOCUS_LEFT || dir == View.FOCUS_RIGHT
        || dir == View.FOCUS_UP || dir == View.FOCUS_DOWN
        || dir == View.FOCUS_FORWARD || dir == View.FOCUS_BACKWARD;
}
if (isValidFocusDirection(dir)) {
    recyclerView.focusSearch(view, dir);
}

Type guard

static boolean isKnownFocusDirection(int dir) {
    switch (dir) {
        case View.FOCUS_LEFT: case View.FOCUS_RIGHT:
        case View.FOCUS_UP: case View.FOCUS_DOWN:
        case View.FOCUS_FORWARD: case View.FOCUS_BACKWARD:
            return true;
        default: return false;
    }
}

Try / catch

null

Prevention

When it happens

Trigger: An external caller (accessibility service, custom keyboard handler, test framework) invoking focusSearch with a direction constant outside the six known View.FOCUS_* values (e.g. View.FOCUS_DOWN === 130 but a typo or a custom constant like 0).

Common situations: Passing 0 or an arbitrary int as direction in requestFocus/arrowScroll tests. Custom focus handling that invents a direction constant.

Related errors


AI-assisted analysis of DrKLO/Telegram@45ab8f4308 (2026-08-14). Data as JSON: /api/errors/c02084c148ef8a1e. Report an issue: GitHub.