[BUG] Cowork remote sandboxes omit user.email / user.account_uuid / organization.id from OTel; local desktop sends them
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.idvalues 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.
Showing cached comments. Read the full discussion on GitHub ↗
3 Comments
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-v18is perfect; byfc-v22it 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.idbehaves 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, whileuser.idandsession.idare present on 100% of rows either way.Anthropic support has confirmed via the in-product messenger that
organization.id,user.account_uuidanduser.emailare "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.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, nouser.account_uuid, and noorganization.id. Consistent with the reports above.Observation 1:
enduser.idandprocess.ownerare absent too. Our collector reads both, in that order, as a fallback whenuser.emailis missing. Neither produced a value on any Cowork record. To rule out a bug on our side we posted a synthetic OTLP log payload withservice.name=coworkcarryingprocess.ownerand 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.owneralone would be enough to put a name back on the record. Note thatenduser.iddoes 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.
Independent confirmation of the
os.versionfinding 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-v22sits 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_modeandworkspace.host_pathsare 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.