Wire errorType into telemetry: port resolve_error_type and set the error.type span attribute
- Dominant language
- TypeScript
- Stars
- 1.4k
- Forks
- 205
- Avg merge
- 3d 12h
- Merged PRs (30d)
- 98
Description
Follow-up to **#583** (port the typed-errors module). Gated on that PR merging.
### Describe the problem
#583 ports `ToolExecutionError` with a public `errorType` property, faithfully matching adk-python's `error_type`. But **nothing in adk-js reads it**. The PR says so explicitly and scopes it out:
> `errorType` is written but not yet read inside this repo — intentional. `core/src/telemetry/tracing.ts` has no `error.type` span-attribute handling today; porting adk-python's `resolve_error_type` is separate follow-up work.
Confirmed on `main` (`bb2dd8f`): grepping `core/src/telemetry/tracing.ts` for `error.type`, `errorType` or `recordException` returns **nothing**. So the property is a correct public API with no consumer, and the OTel semconv `error.type` attribute adk-python emits has no adk-js equivalent.
### What adk-python does
`src/google/adk/telemetry/tracing.py:123-137`:
```python
def resolve_error_type(error: BaseException) -> str:
"""Derives a higher-resolution ``error.type`` label for a failure.
Prefers, in order: a pre-classified ``error_type`` carried by ADK errors; the
HTTP status code for ``google.genai`` ``APIError``s (e.g. ``429``, since the
SDK collapses every 4xx into ``ClientError`` and every 5xx into
``ServerError``); finally the class name.
"""
custom_error_type = getattr(error, "error_type", None)
if custom_error_type is not None:
return str(custom_error_type)
if isinstance(error, genai_errors.APIError):
return str(error.code)
return type(error).__name__
```
Consumed at `tracing.py:226`, with an `error_type` override parameter at `:184` for tool responses that carry a type without throwing.
The middle branch is the interesting one: the genai SDK collapses every 4xx into `ClientError` and every 5xx into `ServerError`, so without the status-code fallback a `429` and a `400` are indistinguishable in traces. That reasoning applies identically to the JS SDK.
### Proposed fix
Port `resolve_error_type` into `core/src/telemetry/tracing.ts` with the same three-tier precedence — ADK `errorType` → genai API error status code → constructor name — and set `error.type` on the relevant spans.
Two things to settle during implementation:
1. **How the JS genai SDK surfaces a status code.** The Python branch keys off `genai_errors.APIError.code`; verify the `@google/genai` equivalent before assuming symmetry.
2. **Which spans get the attribute.** adk-python sets it on tool-execution spans and threads an override for tool responses that report an error without throwing. Match that scope rather than blanket-applying it.
### Why it matters
Without this, `errorType` is parity-only: it round-trips through the public API but never reaches a trace, so the observability benefit that motivated it upstream isn't realised. The enum **values** in #583 were deliberately kept byte-identical to Python precisely because they cross this boundary — this issue is what makes that decision pay off.
### Related
- **#583** — the port this follows up on
- Enum values pinned there: `ToolErrorType`, 9 members, asserted by exact list, order and length
Contributor guide
Assessment
This issue has not been assessed yet.