openclaw - ✅(Solved) Fix [Bug]: Avatar endpoint /avatar/{agentId} returns 404 — workspace-relative avatar path not served [1 pull requests, 2 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#53610Fetched 2026-04-08 01:25:47
View on GitHub
Comments
2
Participants
2
Timeline
7
Reactions
1
Author
Timeline (top)
commented ×2labeled ×2cross-referenced ×1mentioned ×1

The /avatar/{agentId} endpoint always returns 404, even when a valid workspace-relative avatar path (e.g. media/avatars/CoraNeuChatt.png) is correctly configured in both IDENTITY.md and the Appearance → UI settings.

Root Cause

The /avatar/{agentId} endpoint always returns 404, even when a valid workspace-relative avatar path (e.g. media/avatars/CoraNeuChatt.png) is correctly configured in both IDENTITY.md and the Appearance → UI settings.

Fix Action

Fix / Workaround

Possible workaround: using a full http(s) URL as the avatar value works, but workspace-relative paths do not.

PR fix notes

PR #60778: fix(avatar): check ui.assistant.avatar in resolveAvatarSource

Description (problem / solution / changelog)

Problem

resolveAvatarSource in src/agents/identity-avatar.ts only checked agents.list[].identity.avatar and IDENTITY.md, skipping the ui.assistant.avatar config key written by openclaw config set ui.assistant.avatar <path> and the Appearance UI panel.

This meant the HTTP avatar endpoint (/avatar/:id) silently ignored the user's configured avatar, causing the control UI to fall back to the initials placeholder even when the backend could serve the correct image.

Root cause

resolveAssistantIdentity (used by agent.identity.get) already checks cfg.ui?.assistant?.avatar at the highest priority. resolveAvatarSource (feeding the /avatar/:id HTTP endpoint) did not — the two code paths were inconsistent.

Fix

Add cfg.ui?.assistant?.avatar as the highest-priority check in resolveAvatarSource, scoped behind an includeUiOverride option so only the Control UI avatar endpoint opts in — outbound channel callers (outbound/identity.ts, Discord extension, etc.) are unaffected and continue to use per-agent identity avatars.

Priority order when includeUiOverride: true:

  1. ui.assistant.avatar (highest — Control UI surface only)
  2. agents.list[].identity.avatar
  3. IDENTITY.md avatar (lowest)

Tests

Four new cases added to src/agents/identity-avatar.test.ts:

  • ui.assistant.avatar resolves when includeUiOverride: true and no agents.list identity is set
  • ui.assistant.avatar is ignored without includeUiOverride (protects outbound callers)
  • ui.assistant.avatar takes priority over agents.list[].identity.avatar with includeUiOverride
  • ui.assistant.avatar takes priority over IDENTITY.md avatar with includeUiOverride

All 10 tests pass. Lint and typecheck clean.

Related issues

Partially addresses #53610 — that report also involves a 404 on /avatar/:id when the avatar is configured via the Appearance UI. The ui.assistant.avatar value not being surfaced to resolveAvatarSource is one cause of that failure mode.

Related: #48121 (avatar not refreshed on agent switch — different code path, out of scope for this PR)


AI-assisted disclosure

This PR was developed with GitHub Copilot (Claude Sonnet). The fix, tests, and PR description were AI-assisted. I have reviewed all changes and understand what the code does. Testing level: fully tested (all 10 unit tests pass, lint and typecheck clean via commit hook).

Changed files

  • CHANGELOG.md (modified, +1/-0)
  • src/agents/identity-avatar.test.ts (modified, +70/-1)
  • src/agents/identity-avatar.ts (modified, +17/-3)
  • src/gateway/server-http.ts (modified, +2/-1)
RAW_BUFFERClick to expand / collapse

Bug type

Behavior bug (incorrect output/state without crash)

Summary

The /avatar/{agentId} endpoint always returns 404, even when a valid workspace-relative avatar path (e.g. media/avatars/CoraNeuChatt.png) is correctly configured in both IDENTITY.md and the Appearance → UI settings.

Steps to reproduce

  1. Place an image file in the agent workspace at media/avatars/CoraNeuChatt.png (i.e. ~/.openclaw/agents/main/workspace/media/avatars/CoraNeuChatt.png)
    1. Set Avatar: media/avatars/CoraNeuChatt.png in IDENTITY.md
    1. Set the same path in Appearance → UI → Assistant Avatar field, save & apply
    1. Open /__openclaw/control-ui-config.json — confirms "assistantAvatar": "/avatar/main"
    1. Make a HEAD request to https://<host>/avatar/main → 404 Not Found
    1. Tested all plausible URL variants: /avatar/main, /avatars/CoraNeuChatt.png, /media/avatars/CoraNeuChatt.png, /__openclaw/media/avatars/CoraNeuChatt.png — all return 404

Expected behavior

The /avatar/{agentId} endpoint should resolve the configured workspace-relative path and serve the image file. According to the docs (IDENTITY.md template), Avatar: media/avatars/CoraNeuChatt.png is the correct format — the server should find and serve the file from the agent workspace.

Actual behavior

GET /avatar/main returns HTTP 404 Not Found. The /__openclaw/control-ui-config.json correctly shows "assistantAvatar": "/avatar/main", confirming OpenClaw recognizes the config — but the endpoint itself fails to serve the file. All tested URL variants return 404:

  • /avatar/main
    • /avatars/CoraNeuChatt.png
      • /media/avatars/CoraNeuChatt.png
        • /__openclaw/media/avatars/CoraNeuChatt.png The image file physically exists on disk at both:
  • ~/.openclaw/agents/main/workspace/media/avatars/CoraNeuChatt.png
    • ~/.openclaw/media/avatars/CoraNeuChatt.png

OpenClaw version

2026.3.23

Operating system

Windows 11 with WSL2 (Ubuntu), OpenClaw running inside WSL

Install method

npm global

Model

NOT_ENOUGH_INFO (not model-related)

Provider / routing chain

NOT_ENOUGH_INFO (not model-related)

Additional provider/model setup details

No response

Logs, screenshots, and evidence

Impact and severity

No response

Additional information

The /__openclaw/control-ui-config.json endpoint correctly reflects the configured avatar path as "assistantAvatar": "/avatar/main", proving the config is read correctly. The issue is that the /avatar/{agentId} HTTP route either does not exist or fails to resolve the workspace-relative file path to an actual file on disk.

The docs (IDENTITY.md template) explicitly state: "For avatars, use a workspace-relative path like avatars/openclaw.png" — suggesting this feature is intended to work but is broken in the current version.

Possible workaround: using a full http(s) URL as the avatar value works, but workspace-relative paths do not.

extent analysis

Fix Plan

To resolve the issue with the /avatar/{agentId} endpoint returning 404, we need to modify the server-side code to correctly handle workspace-relative paths.

  1. Update the avatar resolver function: Ensure the function that resolves the avatar path is correctly handling workspace-relative paths.
  2. Modify the /avatar/{agentId} endpoint: Update the endpoint to use the corrected resolver function.

Example code snippet (assuming a Node.js environment):

// Updated resolver function
const path = require('path');
const resolveAvatarPath = (agentId, avatarPath) => {
  const workspaceDir = `~/.openclaw/agents/${agentId}/workspace`;
  const absolutePath = path.join(workspaceDir, avatarPath);
  return absolutePath;
};

// Modified /avatar/{agentId} endpoint
app.get('/avatar/:agentId', (req, res) => {
  const agentId = req.params.agentId;
  const avatarPath = getAvatarPathFromConfig(agentId); // assuming this function exists
  const absolutePath = resolveAvatarPath(agentId, avatarPath);
  if (fs.existsSync(absolutePath)) {
    res.sendFile(absolutePath);
  } else {
    res.status(404).send('Avatar not found');
  }
});

Verification

To verify the fix, follow these steps:

  • Update the server-side code with the modified resolver function and endpoint.
  • Restart the server.
  • Make a GET request to /avatar/{agentId} with a valid agentId and workspace-relative avatar path.
  • Verify that the response is a 200 OK with the correct avatar image.

Extra Tips

  • Ensure the IDENTITY.md file is correctly formatted and the avatar path is set to a workspace-relative path.
  • If using a full HTTP(S) URL as the avatar value, ensure it is correctly formatted and accessible.
  • Consider adding error handling and logging to the resolver function and endpoint to help diagnose any future issues.

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…

FAQ

Expected behavior

The /avatar/{agentId} endpoint should resolve the configured workspace-relative path and serve the image file. According to the docs (IDENTITY.md template), Avatar: media/avatars/CoraNeuChatt.png is the correct format — the server should find and serve the file from the agent workspace.

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]: Avatar endpoint /avatar/{agentId} returns 404 — workspace-relative avatar path not served [1 pull requests, 2 comments, 2 participants]