[BUG] Cowork remote sandboxes omit user.email / user.account_uuid / organization.id from OTel; local desktop sends them

Status Open
Reported on v2.1.245
Maintainer reply None cached
Activity 4 comments · opened Aug 28, 2026

Summary

On a Claude Teams plan with OpenTelemetry export enabled, Cowork remote
sandbox sessions emit metrics and traces with the user-identity resource
attributes empty. The same client version running as a local Cowork session
sends them on every row.

The result is unattributable spend: cost and token metrics arrive with no user,
so per-person reporting silently under-counts and the volume lands in an
"unknown" bucket. Over the last 14 days that bucket is 54% of all Cowork rows.

The decisive comparison

Identical client versions (2.1.245 and 2.1.246), same org, same collector, last
14 days. Percentage of rows where each attribute is present:

| Attribute | cowork.surface: remote | local Cowork |
|---|---|---|
| user.email | 9% | 100% |
| user.account_uuid | 9% | 100% |
| organization.id | 9% | 100% |
| user.id | 100% | 100% |
| session.id | 100% | 100% |

Sample size: 6,232 remote rows, 177 local rows.

The three identity attributes fail together as a group. The machine and session
attributes never fail. That pattern suggests the remote sandbox never receives
the authenticated user context, rather than one attribute being dropped on the
way out.

Not a clean version regression

First seen 2026-08-17 on 2.1.234, and it is intermittent per version — which
is why I don't think this is a client code change:

| Version | remote rows | % rows missing user.email |
|---|---|---|
| 2.1.231 | 4,473 | 0% |
| 2.1.233 | 2,936 | 0% |
| 2.1.234 | 1,411 | 9% |
| 2.1.235 | 1,105 | 20% |
| 2.1.236 | 256 | 0% |
| 2.1.237 | 2,997 | 73% |
| 2.1.238 | 1,571 | 37% |
| 2.1.239 | 91 | 0% |
| 2.1.241 | 2,081 | 78% |
| 2.1.245 | 3,355 | 94% |
| 2.1.246 | 2,877 | 87% |
| 2.1.247 | 2,306 | 94% |
| 2.1.248 | 186 | 100% |
| 2.1.250 | 68 | 100% |

The ratio climbing unevenly across versions, with clean versions in between,
looks more like a sandbox image or infrastructure rollout than a client build.

Scope — Cowork remote only

Last 14 days, rows with an empty user.email:

| service.name | rows | % missing email |
|---|---|---|
| claude-code (CLI) | 99,377 | 0% |
| claude-code-desktop | 41,789 | 0% |
| cowork | 23,970 | 54% |

CLI and desktop are unaffected. Within Cowork, only cowork.surface: remote.

What the affected rows do carry

A representative resource/attribute set from an affected row, values removed:

service.name       = cowork
service.version    = 2.1.246
cowork.surface     = remote
instrumentationlibrary.name = com.anthropic.claude_code
user.id            = <64 hex chars, present>
session.id         = <uuid, present>
ccr.session.id     = <cse_… id, present>
os.type            = linux
terminal.type      = linux
user.email         = ""      <-- empty
user.account_uuid  = ""      <-- empty
organization.id    = ""      <-- empty

Why user.id is not a workaround

user.id is present but cannot substitute for the email:

  • It is per-machine/sandbox, not per person — identified users average ~4

distinct values each.

  • Across 90 days, 0 of 261 distinct user.id values ever appear on a row

that also has an email. There is no overlap to build a mapping from.

  • Grouping by it would invent people who don't exist.

Expected vs actual

Expected: a remote Cowork session exports the same identity resource
attributes as the local surface, so OTel consumers can attribute usage per user.

Actual: user.email, user.account_uuid and organization.id are empty on
~91% of remote-sandbox rows, and the proportion has been rising since 2026-08-17.

Environment

  • Claude Teams plan, OpenTelemetry export enabled org-wide via managed settings
  • OTLP → self-hosted OpenTelemetry Collector → Azure Monitor
  • Affected client versions: 2.1.234 through 2.1.250
  • Unaffected on the same collector: Claude Code CLI, Claude Code desktop, local Cowork

Happy to provide privately

Specific ccr.session.id values, user.id hashes, and exact timestamps for
affected sessions — these identify our sessions and machines, so I have not put
them in a public issue. Say where to send them.

View original on GitHub ↗

3 Comments

QJGottschalk-BT · 1 month ago

Update — I found a much stronger signal than the client-version correlation in the original report. It tracks the remote sandbox image (os.version), not the client build.

Cowork remote only, last 30 days, grouped by os.version:

| Sandbox image | First seen | % rows missing user.email | Distinct sandboxes |
|---|---|---|---|
| 6.18.5-fc-v18 | 2026-08-04 | 0% | 37 |
| 6.18.5-fc-v20 | 2026-08-08 | 12% | 102 |
| 6.18.44-fc-v21 | 2026-08-17 | 80% | 87 |
| 6.18.44-fc-v22 | 2026-08-27 | 100% | 10 |

Clean monotonic degradation across four consecutive images. fc-v18 is perfect; by fc-v22 it is total.

That explains why the per-version table in the original report looked erratic — client versions were being mixed across sandbox images. Grouping by image instead removes the noise entirely. So please disregard my earlier framing of "starts at client 2.1.234": the client is not the variable.

Also worth adding: organization.id behaves exactly like the other two. On affected rows it is empty; on attributed rows from the same org and same surface it is populated. So all three identity attributes are absent as a group, while user.id and session.id are present on 100% of rows either way.

Anthropic support has confirmed via the in-product messenger that organization.id, user.account_uuid and user.email are "meant to always be populated from the user's Anthropic account and included in event attributes", and that there is no documented condition under which remote sandboxes should have them empty while local Cowork sessions do not. So this is a regression, not intended behaviour.

myrison · 1 month ago

Adding a third affected organization, plus two controlled observations that may help narrow this.

Setup. macOS, Claude Desktop 1.40609.0, first-party Claude Team organization, OTLP endpoint configured at the organization level. Cowork sessions run in the local VM sandbox. Claude Code CLI on the same machine is unaffected and still carries identity on every record.

What we see. Cowork records arrive with no identity of any kind. Checked again today on five separate sessions: no user.email, no user.account_uuid, and no organization.id. Consistent with the reports above.

Observation 1: enduser.id and process.owner are absent too. Our collector reads both, in that order, as a fallback when user.email is missing. Neither produced a value on any Cowork record. To rule out a bug on our side we posted a synthetic OTLP log payload with service.name=cowork carrying process.owner and nothing else identifying. That one was attributed correctly. So the reader works and the fields genuinely are not on the wire. This matches the confirmation in #89483 and means the usual fallback does not rescue Cowork.

Observation 2: host-set resource attributes do not reach Cowork either. We set a custom resource attribute of our own on the host, via OTEL_RESOURCE_ATTRIBUTES, for the desktop app. It is absent from every Cowork record, while the same attribute in the synthetic payload above was stored correctly. So it is not only the identity group that is missing: nothing configured on the host appears on Cowork's records. We have not established whether that part is intended.

Timing. Our earliest nameless Cowork records are from 2026-08-18, which is consistent with the fc-v21 image date of 2026-08-17 given above. Records before that date are attributed normally.

Impact. Cowork spend cannot be attributed to a person at all right now, so it lands in an unattributed bucket. There is no per-user workaround we have found: the environment route does not reach the sandbox, and the organization-level resource attributes field is a single value for the whole company, so it cannot carry a person.

What would fix it for us. Restoring whatever the sandbox previously passed through, so that the resource attributes the desktop constructs survive into the guest. process.owner alone would be enough to put a name back on the record. Note that enduser.id does not appear to be an option for first-party organizations, so please do not treat it as the fallback here.

Happy to supply anonymised record counts or a redacted payload if that would help.

peterzajac-mbi · 1 month ago

Independent confirmation of the os.version finding from a fourth organization — your sandbox-image hypothesis holds on our data, on a different collector and a different backend (self-hosted OTel Collector → ClickHouse, first-party Claude Team org).

Remote Cowork rows over 30 days, grouped by os.version:

| Sandbox image | First seen | Rows | % missing user.email |
|---|---|---|---|
| 6.18.5-fc-v18 | 2026-08-04 | 11,392 | 0% |
| 6.18.5-fc-v20 | 2026-08-07 | 41,028 | 9.3% |
| 6.18.44-fc-v21 | 2026-08-19 | 23,806 | 77.5% |
| 6.18.44-fc-v22 | 2026-08-27 | 7,988 | 64.2% |

Same four images, same first-seen dates, same monotonic climb. Our fc-v22 sits at 64% rather than your 100%, but it is the newest image and still filling out. As you found, grouping by client build produces an erratic table — we had originally reported this to support as a 2.1.234 regression and that framing was wrong for the same reason.

One addition that may narrow it further: on affected rows the missing set is not limited to the three identity attributes. app.version, os.type, os.version, host.arch, service.name, service.version, process.owner, claude.deployment_mode and workspace.host_paths are also absent on 100% of them, while the OTel resource attributes carrying those same values are intact. So the whole session-context block fails to reach log attributes, not just identity. Details and our recovery-attempt results are in #88490.

Showing cached comments. Read the full discussion on GitHub ↗