[BUG] Windows Desktop app + SSO (Team plan): oauthAccount not hydrated to ~/.claude.json, OTel metrics emitted without user identity
Preflight Checklist
- [x] I have searched existing issues and this hasn't been reported yet
- [x] This is a single bug report (please file separate reports for different bugs)
- [x] I am using the latest version of Claude Code
What's Wrong?
What's Wrong?
When Claude Code runs from the Windows Desktop app with SSO login (Team plan), the OpenTelemetry metrics it exports are emitted with these resource attributes empty on every series:
user.emailuser.account_uuidorganization.id
Only user.id (the anonymous per-install hash) is populated. API calls themselves succeed normally — authentication works — so the user can use Claude Code, but their telemetry cannot be attributed back to them in dashboards (claude_code_session_count_total, claude_code_token_usage_tokens_total, claude_code_cost_usage_USD_total, etc. all show empty user_email in Prometheus).
The same user, on the same machine, running Claude Code under WSL Ubuntu (separate install, same SSO account) emits all three attributes correctly. So the issue is specific to the Windows Desktop app surface, not the SSO/Team account.
Root cause (from local inspection)
The bundled CLI populates OTel identity attributes by reading the oauthAccount block from ~/.claude.json. On the Windows Desktop install:
$j = Get-Content "$env:USERPROFILE\.claude.json" -Raw | ConvertFrom-Json
$j.oauthAccount # → not present
$j.email # → not present
$j.accountUuid # → not present
$j.organizationUuid # → not present
$j.userID # → present (64-char hash)
The OAuth tokens themselves DO exist — they're stored in %APPDATA%\Claude\config.json under the key oauth:tokenCache (DPAPI-encrypted, ~1.3 KB, prefix v10…). That's where the desktop app reads them from for API auth.
But the desktop app's SSO login flow never writes the unencrypted identity fields (oauthAccount.emailAddress, accountUuid, organizationUuid) into ~/.claude.json, which is what the embedded CLI's telemetry pipeline expects. So:
- Auth works (tokens are in the encrypted cache)
- Telemetry initializes (OTLP pipeline runs, metrics arrive)
- But identity attributes are blank (the CLI looks for them in an empty place)
A /logout followed by a fresh SSO login through the desktop app does NOT fix this — the oauthAccount block remains absent after re-login.
Relation to #10972
This appears to be the same root-cause class as #10972 ("Claude Code for VSCode Does Not Send user.account_uuid When Metrics Are Enabled"), but on a different GUI surface (Windows Desktop app vs. VSCode extension). Both surfaces authenticate via host-managed OAuth and skip hydrating oauthAccount into ~/.claude.json, so any host-GUI path leaves the embedded CLI without the data it needs for OTel resource attributes.
A single fix in the embedded CLI's startup path that hydrates oauthAccount from /v1/oauth/userinfo (or equivalent) when a token is present would resolve both issues.
What Should Happen?
What Should Happen?
OTel resource attributes user.email, user.account_uuid, and organization.id should be populated on metrics for any OAuth-authenticated session, per the official monitoring docs. This works correctly on Linux/WSL installs of the same user with the same SSO account.
Specifically: after a successful SSO login through the Windows Desktop app, ~/.claude.json should contain a populated oauthAccount block with emailAddress, accountUuid, and organizationUuid — matching what the standalone CLI's /login flow writes on Linux.
Error Messages/Logs
No error messages — telemetry initializes silently and metrics flow normally to the OTLP endpoint. The bug is in the *content* of the resource attributes, not in the export pipeline.
Local inspection of `~/.claude.json` shows the data simply isn't there to attach (see "What's Wrong?" for the PowerShell snippet).
Steps to Reproduce
- Install the Windows Desktop app on a Windows 11 machine.
- Log in via SSO (Team plan).
- Configure managed settings to export OTLP metrics:
{
"env": {
"CLAUDE_CODE_ENABLE_TELEMETRY": "1",
"OTEL_EXPORTER_OTLP_ENDPOINT": "http://<your-otel-collector>:4318",
"OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE": "cumulative",
"OTEL_EXPORTER_OTLP_PROTOCOL": "http/protobuf",
"OTEL_LOGS_EXPORTER": "none",
"OTEL_METRICS_EXPORTER": "otlp"
}
}
- Run any Claude Code session in the desktop app.
- Query the resulting metrics in Prometheus (or whatever your OTLP collector feeds) — observe
user_email="",user_account_uuid="",organization_id=""on the series produced by this install. - Inspect
~/.claude.jsonand confirm theoauthAccountblock is absent:
(Get-Content $env:USERPROFILE\.claude.json | ConvertFrom-Json).oauthAccount
# → empty output
- (Optional control) Repeat the same test from a WSL Ubuntu install on the same machine, same SSO account —
oauthAccountIS present and metrics emit correctly. Confirms the bug is desktop-app-specific.
Claude Model
None
Is this a regression?
I don't know
Last Working Version
_No response_
Claude Code Version
2.1.128 (Claude Code) — output of %APPDATA%\Claude\claude-code\2.1.128\claude.exe --version (the CLI bundled by the desktop app). Host: Claude Desktop app 1.6259.1 (5095e7) 2026-05-06T03:26:09.000Z on Windows 11.
Platform
Anthropic API
Operating System
Windows
Terminal/Shell
Other
Additional Information
The documented workaround does not work on this surface
The monitoring docs recommend setting OTEL_RESOURCE_ATTRIBUTES to add custom attributes when OAuth-derived ones aren't available:
"OTEL_RESOURCE_ATTRIBUTES": "enduser.id=user@example.com"
I added this to my org-pushed managed settings (visible in ~/.claude/remote-settings.json after sync, contents verified to include the new env var). The OTHER env vars in the same block ARE clearly being applied — OTEL_EXPORTER_OTLP_ENDPOINT is honored, OTEL_EXPORTER_OTLP_METRICS_TEMPORALITY_PREFERENCE=cumulative is honored, metrics arrive normally. But the enduser_id label never appears on any metric, even after a full desktop-app quit + relaunch + new session.
This is consistent with #4338 ("OTEL_RESOURCE_ATTRIBUTES does not apply to logs") — same env-var-ignored pattern, just on metrics rather than logs. So on the Windows Desktop + SSO surface, there is currently no working workaround for the missing identity attributes: OAuth hydration is broken (this bug), and the documented escape hatch is also broken (#4338 extended to metrics).
Suggested fix
In the embedded CLI's startup path, when an OAuth token is present (from any source — Desktop app, VSCode extension, native CLI), call /v1/oauth/userinfo (or equivalent) and hydrate oauthAccount into ~/.claude.json if the block is absent. This would fix both this issue and #10972 with a single change.
Independently, fixing #4338 to also cover metrics on the Windows Desktop surface would at least restore the documented workaround.
Related issues
- #10972 — same root-cause class, VSCode extension surface
- #4338 —
OTEL_RESOURCE_ATTRIBUTESignored (closed; appears to still affect metrics on Windows Desktop) - #46204 — Windows enterprise OTel issue (different failure mode but adjacent surface)
This issue has 4 comments on GitHub. Read the full discussion on GitHub ↗