Skip to content

[Bug] Session dropdown shows key instead of label (2026.3.12 regression) #45120

@luzhidong

Description

@luzhidong

Bug Description

In OpenClaw 2026.3.12, the session dropdown in the Control UI chat tab shows session keys (e.g., agent:main:subagent:4f2146de-887b-4176-9abe-91140082959b) instead of human-readable labels (e.g., cron-config-check).

Environment

  • OpenClaw version: 2026.3.12 (6472949)
  • Platform: Linux x64

Steps to Reproduce

  1. Open Control UI
  2. Navigate to Chat tab
  3. Click on session dropdown
  4. Observe that sessions are displayed as keys, not labels

Expected Behavior

Sessions should display their label field (e.g., "cron-prompt-analysis") instead of the raw key.

Root Cause

The resolveSessionScopedOptionLabel function in ui/src/ui/app-render.helpers.ts does not properly use the row.label field. It prioritizes displayName over label.

Fix

diff --git a/ui/src/ui/app-render.helpers.ts b/ui/src/ui/app-render.helpers.ts
index 0a2003f..57923ab 100644
--- a/ui/src/ui/app-render.helpers.ts
+++ b/ui/src/ui/app-render.helpers.ts
@@ -536,22 +536,24 @@ function resolveSessionScopedOptionLabel(
   row?: SessionsListResult["sessions"][number],
   rest?: string,
 ) {
-  const base = rest?.trim() || key;
-  if (!row) {
-    return base;
+  // Priority: label > displayName > key
+  const label = typeof row?.label === "string" && row.label.trim().length > 0
+    ? row.label.trim()
+    : null;
+  const displayName = typeof row?.displayName === "string" && row.displayName.trim().length > 0
+    ? row.displayName.trim()
+    : null;
+
+  // Use label if available
+  if (label) {
+    return \`\${key} · \${label}\`;
   }
-  const displayName =
-    typeof row.displayName === "string" && row.displayName.trim().length > 0
-      ? row.displayName.trim()
-      : null;
-  const label = typeof row.label === "string" ? row.label.trim() : "";
-  const showDisplayName = Boolean(
-    displayName && displayName !== key && displayName !== label && displayName !== base,
-  );
-  if (!showDisplayName) {
-    return base;
+  // Fall back to displayName if available
+  if (displayName && displayName !== key) {
+    return \`\${key} · \${displayName}\`;
   }
-  return \`\${base} · \${displayName}\`;
+  // Fall back to key
+  return key;
 }

Session Data (verified)

The sessions API correctly returns the label field:

{
  "key": "agent:main:subagent:4f2146de-887b-4176-9abe-91140082959b",
  "label": "cron-config-check",
  "displayName": "webchat:g-agent-main-subagent-..."
}

Related

This is a regression introduced in version 2026.3.12.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions