openclaw - ✅(Solved) Fix [Bug]: Custom avatar disappears after 1-2 seconds when navigating in WebUI — frontend state management issue [2 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#71595Fetched 2026-04-26 05:10:56
View on GitHub
Comments
1
Participants
2
Timeline
15
Reactions
0
Author
Participants
Timeline (top)
referenced ×11cross-referenced ×2closed ×1commented ×1

Root Cause

Possibly the same root cause as #10249, but that issue focused on the backend 404 problem (now fixed). This report focuses on the frontend state persistence aspect.

Fix Action

Fixed

PR fix notes

PR #71666: Fix/avatar disappears on nav

Description (problem / solution / changelog)

Summary

  • Problem: After navigating away and back in the WebUI, a custom agent avatar briefly appears (1-2s) then is replaced by the default "A" placeholder.
  • Why it matters: Broken UX — users with custom avatars set experience visual regression on every navigation.
  • What changed: Three refreshChatAvatar() call sites now sync the resulting chatAvatarUrl blob URL to the Lit @state() reactive field (AppViewState.chatAvatarUrl), so the chat view re-renders with the correct avatar instead of falling back to the default.
  • What did NOT change: No backend changes, no API changes, no avatar upload flow changes.

Change Type

  • Bug fix

Scope

  • UI / DX

Linked Issue/PR

  • Closes #71595
  • Related #

Root Cause

  • Root cause: refreshChatAvatar() correctly fetches the avatar and stores the blob URL in ChatHost.chatAvatarUrl, but the Lit @state() field AppViewState.chatAvatarUrl was never updated. The chat view reads state.chatAvatarUrl with a null-coalesce fallback to the backend config avatar, so it always received null and showed the default.
  • Missing detection / guardrail: No Lit state sync after refreshChatAvatar() — the reactive field was orphaned.

Regression Test Plan

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient (manual WebUI test)
  • Target test or file: N/A — this is a UI state synchronization issue with no existing automated coverage.
  • Scenario the test should lock in: Navigate between sessions or views in the WebUI with a custom avatar set; avatar must remain visible.
  • Why this is the smallest reliable guardrail: The bug is a state flow gap between two Lit controller layers; a seam test would require mocking both layers.
  • Existing test that already covers this (if any): None found.
  • If no new test is added, why not: The fix is a simple one-line sync operation; adding a test for Lit internal state would require significant test infrastructure mocking that does not currently exist.

User-visible / Behavior Changes

  • Custom agent avatar now persists correctly after navigating between views/sessions in the WebUI.

Diagram

Before: [refreshChatAvatar] -> ChatHost.chatAvatarUrl = blob URL -> AppViewState.chatAvatarUrl = null (never updated) [chat view renders] -> reads state.chatAvatarUrl -> null -> falls back to default avatar

After: [refreshChatAvatar] -> ChatHost.chatAvatarUrl = blob URL -> AppViewState.chatAvatarUrl = blob URL (synced) [chat view renders] -> reads state.chatAvatarUrl -> blob URL -> correct avatar shown

Security Impact

  • New permissions/capabilities? (No)
  • Secrets/tokens handling changed? (No)
  • New/changed network calls? (No)
  • Command/tool execution surface changed? (No)
  • Data access scope changed? (No)

Repro + Verification

Environment

  • OS: any
  • Runtime/container: WebUI (browser)
  • Model/provider: any
  • Integration/channel (if any): WebUI only

Steps

  1. Set a custom agent avatar in the OpenClaw WebUI.
  2. Navigate away from the main chat view (e.g., open a file, switch sessions, navigate to Settings then back).
  3. Observe the avatar in the chat view.

Expected

Custom avatar remains visible after navigation.

Actual

Avatar briefly appears then replaced by default "A" placeholder (before fix).

Human Verification

  • Verified scenarios: Applied fix locally, confirmed three call sites cover all entry points (gateway connect, session init/refresh, session switch).
  • Edge cases checked: Avatar upload flow already sets state.chatAvatarUrl directly — no regression there.
  • What you did not verify: Cannot run WebUI locally without full gateway environment.

Compatibility / Migration

  • Backward compatible? (Yes)
  • Config/env changes? (No)
  • Migration needed? (No)

Risks and Mitigations

  • None — fix is a single reactive state sync line at three existing call sites with no behavioral side effects.

Changed files

  • src/agents/model-ref-profile.test.ts (modified, +16/-0)
  • src/agents/model-ref-profile.ts (modified, +4/-3)
  • ui/src/ui/app-chat.ts (modified, +16/-10)
  • ui/src/ui/app-gateway.ts (modified, +8/-1)
  • ui/src/ui/app-render.helpers.ts (modified, +7/-1)

PR #71698: fix(ui): sync chatAvatarUrl after refreshChatAvatar to prevent avatar flicker

Description (problem / solution / changelog)

Summary

After navigating away and back in the WebUI, the custom avatar would briefly appear then be replaced by the default placeholder within 1-2s.

Root Cause

refreshChatAvatar() correctly fetches the avatar blob and stores it in ChatHost.chatAvatarUrl, but the Lit @state() field AppViewState.chatAvatarUrl was never updated. The chat view reads state.chatAvatarUrl, so it always fell back to the default avatar config.

Fix

refreshChatAvatar() now returns string | null (the resolved blob URL or null). Callers use void refreshChatAvatar().then(avatarUrl => {...}) to sync the result to the host/state chatAvatarUrl field, triggering Lit's reactive re-render.

Three call sites updated:

  • onHello (connectGateway) — gateway hello after connect
  • refreshChat() — session init and refresh
  • switchChatSession() — session switching

Files Changed

  • ui/src/ui/app-chat.tsrefreshChatAvatar returns string | null, refreshChat syncs the result
  • ui/src/ui/app-gateway.tsonHello uses .then() to sync avatar
  • ui/src/ui/app-render.helpers.tsswitchChatSession uses .then() to sync avatar

Fixes openclaw/openclaw#71595

Changed files

  • ui/src/ui/app-chat.ts (modified, +20/-11)
  • ui/src/ui/app-gateway.ts (modified, +7/-1)
  • ui/src/ui/app-render.helpers.ts (modified, +6/-1)
RAW_BUFFERClick to expand / collapse

Bug Summary

The avatar backend configuration is completely correct — the issue is a frontend state management bug where the custom avatar is overridden by the default placeholder after a short delay (1–2 seconds) when navigating within the WebUI.

Detailed Observation

Backend (verified working)

  • agents.list[0].identity.avatar is correctly set to "avatar.png"
  • The file /root/.openclaw/workspace/avatar.png (512×512, 264KB) is confirmed present and valid
  • resolveAgentAvatar() correctly returns kind: "local" with the resolved file path
  • No 404 on /avatar/main — the backend serves the image correctly

Frontend (bug present)

  1. Initial page load → avatar displays correctly
  2. Navigate to another page (e.g. Channels) via sidebar → avatar component unmounts
  3. Navigate back → avatar reappears for 1–2 seconds, then gets replaced by the default "A" placeholder

This indicates the avatar state is not persisted in the global store. After component remount, it re-fetches correctly, but a subsequent state update (WebSocket message, heartbeat, or other event) overwrites it with DEFAULT_ASSISTANT_IDENTITY.avatar.

Environment

  • OpenClaw version: 2026.4.23 (a979721)
  • OS: Ubuntu 24.04
  • Browser: Chrome (multiple versions tested)
  • Avatar path: avatar.png (relative to workspace)

Related

Possibly the same root cause as #10249, but that issue focused on the backend 404 problem (now fixed). This report focuses on the frontend state persistence aspect.

Suggested Fix

Ensure the avatar URL/state is stored in the global application store (not just local component state), so it survives:

  • Route transitions
  • WebSocket message updates
  • Heartbeat/refetch cycles

extent analysis

TL;DR

Update the frontend code to store the avatar URL/state in the global application store to persist it across route transitions and updates.

Guidance

  • Review the current implementation of the avatar component and identify where the avatar state is being stored and updated.
  • Modify the code to store the avatar URL/state in the global application store, ensuring it survives route transitions and WebSocket message updates.
  • Verify that the avatar state is correctly updated and persisted when navigating between pages and receiving updates.
  • Consider implementing a mechanism to handle cases where the avatar state is updated externally, such as through a WebSocket message, to ensure the global store is updated accordingly.

Example

// Pseudocode example of storing avatar state in global application store
const globalStore = {
  avatarUrl: null,
  // ...
};

const updateAvatar = (newAvatarUrl) => {
  globalStore.avatarUrl = newAvatarUrl;
  // Update the avatar component with the new URL
};

Notes

The provided information suggests that the issue is related to the frontend state management, and storing the avatar state in the global application store should resolve the problem. However, the exact implementation details may vary depending on the specific frontend framework and architecture being used.

Recommendation

Apply the suggested fix by updating the frontend code to store the avatar URL/state in the global application store, as this should resolve the issue of the custom avatar being overridden by the default placeholder after a short delay.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix [Bug]: Custom avatar disappears after 1-2 seconds when navigating in WebUI — frontend state management issue [2 pull requests, 1 comments, 2 participants]