Skip to content

fix(ui): correct J/K keyboard navigation direction in Logs view#24344

Open
NIK-TIGER-BILL wants to merge 2 commits intoBerriAI:mainfrom
NIK-TIGER-BILL:fix/jk-keyboard-nav-logs-view
Open

fix(ui): correct J/K keyboard navigation direction in Logs view#24344
NIK-TIGER-BILL wants to merge 2 commits intoBerriAI:mainfrom
NIK-TIGER-BILL:fix/jk-keyboard-nav-logs-view

Conversation

@NIK-TIGER-BILL
Copy link

Problem

Closes #24279

In the Logs view side panel, J and K keyboard shortcuts navigate in the opposite direction compared to the UI buttons.

Input Expected Actual
J key Move down (older log) Moves up (newer log)
K key Move up (newer log) Moves down (older log)

Root Cause

In useKeyboardNavigation.ts the switch cases were swapped:

// Before (wrong):
case KEY_J_LOWER:
case KEY_J_UPPER:
  selectPreviousLog();  // J went UP — should go DOWN
  break;
case KEY_K_LOWER:
case KEY_K_UPPER:
  selectNextLog();      // K went DOWN — should go UP
  break;

J is the vim-convention key for moving down (to older entries in a newest-first list) and K for moving up (to newer entries). The UI buttons already implement this correctly; only the keyboard handler was inverted.

Solution

Swap the handler calls so keyboard behaviour matches the UI buttons and vim convention:

// After (correct):
case KEY_J_LOWER:
case KEY_J_UPPER:
  selectNextLog();     // J moves DOWN to older log ✓
  break;
case KEY_K_LOWER:
case KEY_K_UPPER:
  selectPreviousLog(); // K moves UP to newer log ✓
  break;

Testing

  • Open any log entry side panel
  • Press J → navigates to the next (older) log ✓
  • Press K → navigates to the previous (newer) log ✓
  • Matches the behaviour of the ↓ and ↑ UI buttons respectively

NIK-TIGER-BILL added 2 commits March 22, 2026 07:13
…gh logging

Fixes BerriAI#24281

When proxying models like anthropic/deepseek-reasoner, certain SSE stream
events contain JSON structures that the Anthropic chunk parser cannot handle
(e.g. thinking blocks, extended metadata), producing:

    streaming_handler.py:197 - Error in _route_streaming_logging_to_handler:
    Expecting value: line 1 column 3 (char 2)

Previously _build_complete_streaming_response only caught StopIteration /
StopAsyncIteration from convert_str_chunk_to_generic_chunk. Any other
exception (json.JSONDecodeError, KeyError, …) propagated all the way up and
was silently swallowed by the broad except in
_route_streaming_logging_to_handler — but not before emitting a noisy
ERROR-level log on every request.

Fix: add an except-Exception guard around the per-event conversion loop so
that individual unparseable events are skipped with a DEBUG-level log while
all valid events in the same stream are still processed and logged correctly.
The overall logging call is no longer aborted by a single bad event.
Fixes BerriAI#24279

J and K were mapped to the wrong navigation functions:
- Pressing J called selectPreviousLog() (moved UP to newer)
- Pressing K called selectNextLog()     (moved DOWN to older)

This is the opposite of the UI buttons and of standard vim-style
navigation where J = down (older entry in newest-first list) and
K = up (newer entry).

Fix: swap the J and K cases so they match both the UI buttons and
vim convention:
- J → selectNextLog()     (moves down to the next / older log)
- K → selectPreviousLog() (moves up to the previous / newer log)
@vercel
Copy link

vercel bot commented Mar 22, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
litellm Ready Ready Preview, Comment Mar 22, 2026 7:22am

Request Review

@CLAassistant
Copy link

CLA assistant check
Thank you for your submission! We really appreciate it. Like many open source projects, we ask that you sign our Contributor License Agreement before we can accept your contribution.


NIK-TIGER-BILL seems not to be a GitHub user. You need a GitHub account to be able to sign the CLA. If you have already a GitHub account, please add the email address used for this commit to your account.
You have signed the CLA already but the status is still pending? Let us recheck it.

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Mar 22, 2026

Greptile Summary

This PR contains two unrelated fixes bundled together: a one-line keyboard navigation inversion fix in the Logs view UI, and a resilience improvement in the Anthropic SSE passthrough logging handler.

  • useKeyboardNavigation.ts: Swaps selectNextLog and selectPreviousLog in the J/K switch cases to match vim convention (J = down/older, K = up/newer) and align with the existing UI button behaviour. The JSDoc comment is also updated accordingly. The fix is minimal, correct, and well-described.
  • anthropic_passthrough_logging_handler.py: Adds an except Exception fallback inside the SSE event processing loop so that a single unparseable event (e.g. from anthropic/deepseek-reasoner producing non-standard SSE) does not abort the entire passthrough logging call. The intent is valid, but the catch-all exception type and debug-level logging are concerns — genuine regressions in convert_str_chunk_to_generic_chunk would be silently swallowed and invisible in production logs.

Confidence Score: 4/5

  • Safe to merge with minor concerns — the UI fix is correct and the Python change is a net improvement, though the overly broad exception handler should ideally be narrowed before merging.
  • The keyboard navigation fix is trivially correct. The Python change improves resilience but introduces a broad except Exception that could hide real bugs and uses debug-level logging that makes production failures invisible. Neither issue is blocking, but the Python change carries a small risk of masking future regressions.
  • litellm/proxy/pass_through_endpoints/llm_provider_handlers/anthropic_passthrough_logging_handler.py — review the exception scope and log level.

Important Files Changed

Filename Overview
ui/litellm-dashboard/src/components/view_logs/LogDetailsDrawer/useKeyboardNavigation.ts Correct one-line fix swapping selectNextLog/selectPreviousLog in the J/K keyboard handlers to match vim conventions and existing UI button behaviour. Comment and JSDoc updated to match. No issues found.
litellm/proxy/pass_through_endpoints/llm_provider_handlers/anthropic_passthrough_logging_handler.py Adds a catch-all except Exception handler to tolerate malformed SSE events from non-standard Anthropic pass-through models. The intent is sound, but the overly broad exception type risks silently masking genuine parsing regressions, and debug-level logging makes the failures invisible in production.

Sequence Diagram

sequenceDiagram
    participant User as User (keyboard)
    participant Hook as useKeyboardNavigation
    participant Drawer as LogDetailsDrawer

    User->>Hook: keydown "j" / "J"
    Hook->>Hook: selectNextLog() [index + 1]
    Hook->>Drawer: onSelectLog(allLogs[currentIndex + 1])
    Drawer-->>User: Show older log ↓

    User->>Hook: keydown "k" / "K"
    Hook->>Hook: selectPreviousLog() [index - 1]
    Hook->>Drawer: onSelectLog(allLogs[currentIndex - 1])
    Drawer-->>User: Show newer log ↑

    User->>Hook: keydown "Escape"
    Hook->>Drawer: onClose()
    Drawer-->>User: Drawer closed
Loading

Last reviewed commit: "fix(ui): correct J/K..."

Comment on lines +293 to +306
except Exception as e:
# Some models (e.g. anthropic/deepseek-reasoner) may emit SSE
# events with non-standard JSON or extra fields that the
# Anthropic chunk parser cannot handle. Silently skip
# individual malformed events so that valid events in the same
# stream are still logged rather than dropping the entire
# logging call with an unhandled JSONDecodeError.
verbose_proxy_logger.debug(
"Skipping unparseable Anthropic SSE event during passthrough "
"logging. Error: %s. Event (truncated): %.200s",
str(e),
event_str,
)
continue
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Overly broad exception handler may swallow genuine bugs

The catch-all except Exception will silently suppress any exception thrown by convert_str_chunk_to_generic_chunk — including AttributeError, TypeError, MemoryError, and other errors that indicate real bugs in the conversion logic rather than malformed SSE payloads.

Additionally, the failure is logged only at debug level, meaning silent data-loss in production will be invisible unless a user explicitly enables debug logging. Consider narrowing to the specific parsing-related exceptions that can be expected from malformed SSE events and raising the log level to warning so operators can detect systematic parsing failures:

except (StopIteration, StopAsyncIteration):
    break
except (json.JSONDecodeError, ValueError, KeyError) as e:
    # Some models (e.g. anthropic/deepseek-reasoner) may emit SSE
    # events with non-standard JSON or extra fields that the
    # Anthropic chunk parser cannot handle.  Silently skip
    # individual malformed events so that valid events in the same
    # stream are still logged rather than dropping the entire
    # logging call with an unhandled JSONDecodeError.
    verbose_proxy_logger.warning(
        "Skipping unparseable Anthropic SSE event during passthrough "
        "logging. Error: %s. Event (truncated): %.200s",
        str(e),
        event_str,
    )
    continue

This way, unexpected errors (e.g. regressions in the iterator logic) still propagate and are surfaced, while known parsing failures are handled gracefully and visible at warning level in production logs.

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]: Logs view keyboard navigation J/K is inverted vs UI buttons

2 participants