# error.type: the OpenTelemetry error attribute

> What OpenTelemetry's error.type attribute holds, when to set it, the _OTHER fallback, and real values from agent and transaction traces.

Source: https://hashspan.dev/learn/otel-attributes/error


From semantic-conventions v1.44.0 (e10a930). Synced 2026-10-18.

## Short answer

`error.type` is a Stable attribute that names the class of error an operation ended with, such as `timeout`, an exception class or a status code. Set it only when the operation failed, keep its values few, and use `_OTHER` when nothing better fits. `error.message` is deprecated.

## What do the error.* attributes describe?

Span status says that something failed. `error.type` says what kind of failure it was, in a form you can group by. That is why HTTP, RPC and GenAI spans all reference it.

The convention asks for a predictable, low-cardinality value: an exception's class name, a domain code, or a short label like `timeout`. A successful operation SHOULD NOT have one.

## Which spans set them?

| Span name | Kind | Convention |
|---|---|---|
| `{method} {target}` | CLIENT | http.client |
| `{method} {target}` | SERVER | http.server |
| `{rpc.method}` | CLIENT | rpc.call.client |
| `{rpc.method}` | SERVER | rpc.call.server |
| `{rpc.method}` | CLIENT | rpc.connect_rpc.call.client |
| `{rpc.method}` | SERVER | rpc.connect_rpc.call.server |
| `{rpc.method}` | CLIENT | rpc.grpc.call.client |
| `{rpc.method}` | SERVER | rpc.grpc.call.server |
| `{rpc.method}` | CLIENT | rpc.jsonrpc.call.client |
| `{rpc.method}` | SERVER | rpc.jsonrpc.call.server |
| `{rpc.method}` | CLIENT | rpc.dubbo.call.client |
| `{rpc.method}` | SERVER | rpc.dubbo.call.server |
| `{gen_ai.operation.name} {gen_ai.request.model}` | CLIENT | gen_ai.client.inference |
| `{gen_ai.operation.name} {gen_ai.request.model}` | CLIENT | gen_ai.embeddings.client |
| `{gen_ai.operation.name} {gen_ai.data_source.id}` | CLIENT | gen_ai.retrieval.client |
| `{gen_ai.operation.name}` | CLIENT | gen_ai.fetch_response.client |
| `{gen_ai.operation.name}` | CLIENT | gen_ai.memory.client |
| `create_agent {gen_ai.agent.name}` | CLIENT | gen_ai.create_agent.client |
| `invoke_agent {gen_ai.agent.name}` | CLIENT | gen_ai.invoke_agent.client |
| `invoke_agent {gen_ai.agent.name}` | INTERNAL | gen_ai.invoke_agent.internal |
| `execute_tool {gen_ai.tool.name}` | INTERNAL | gen_ai.execute_tool.internal |
| `invoke_workflow {gen_ai.workflow.name}` | INTERNAL | gen_ai.invoke_workflow.internal |
| `plan {gen_ai.agent.name}` | INTERNAL | gen_ai.plan.internal |
| `{mcp.method.name}` | CLIENT | mcp.client |
| `{mcp.method.name}` | SERVER | mcp.server |
| `{gen_ai.operation.name} {gen_ai.request.model}` | CLIENT | openai.gen_ai.client.inference (refines gen_ai.client.inference) |
| `{gen_ai.operation.name}` | CLIENT | openai.fetch_response.client (refines gen_ai.fetch_response.client) |
| `{gen_ai.operation.name} {gen_ai.request.model}` | CLIENT | azure.ai.gen_ai.client.inference (refines gen_ai.client.inference) |
| `{gen_ai.operation.name} {gen_ai.request.model}` | CLIENT | anthropic.gen_ai.client.inference (refines gen_ai.client.inference) |
| `{gen_ai.operation.name} {gen_ai.request.model}` | CLIENT | aws.bedrock.gen_ai.client.inference (refines gen_ai.client.inference) |
| `execute_tool {gen_ai.tool.name} {gen_ai.skill.name}` | INTERNAL | gen_ai.execute_tool.load_skill.internal (refines gen_ai.execute_tool.internal) |
| `execute_tool {gen_ai.tool.name} {gen_ai.skill.name} {gen_ai.skill.resource.name}` | INTERNAL | gen_ai.execute_tool.read_skill_resource.internal (refines gen_ai.execute_tool.internal) |
| `gen_ai.execute_tool.command.internal` | INTERNAL | gen_ai.execute_tool.command.internal (refines gen_ai.execute_tool.internal) |

## What does a real span record?

Span `confirm 31337` (CLIENT):

| Attribute | Value |
|---|---|
| `blockchain.tx.status` | `reverted` |
| `blockchain.tx.revert.reason` | `WithdrawalLimitExceeded(100, 250)` |
| `error.type` | `reverted` |

From a real run on 2026-10-18: `@hashspan/viem` 1.1.1 with viem 2.57.7 against a local Anvil node on port 8545. [The page this run is from](https://hashspan.dev/docs/viem-opentelemetry).

The span status was Error. In the AI SDK recipe run on 2026-10-03, a send whose gas estimate failed recorded `error.type` `ContractFunctionExecutionError`, viem's error class.

## Which error.type values does hashspan record?

Outcomes from chain data, such as `reverted`, and its own labels, such as `timeout` when the wait for a receipt ran out and `not_on_chain` when a reorganisation removed the transaction. Otherwise the error class name, such as `TransactionExecutionError`, or `_OTHER`.

The full list is in the [span status table](https://hashspan.dev/docs/reference/semantic-conventions#span-status) of hashspan's conventions.

## The `error.*` attribute

### `error.type`

- Type: string
- Stability: Stable
- Describes a class of error the operation ended with.
- Values: `_OTHER`
- Set on:
  - `{method} {target}` CLIENT: http.client (conditionally required)
  - `{method} {target}` SERVER: http.server (conditionally required)
  - `{rpc.method}` CLIENT: rpc.call.client (conditionally required), rpc.connect_rpc.call.client (conditionally required), rpc.grpc.call.client (conditionally required), rpc.jsonrpc.call.client (conditionally required), rpc.dubbo.call.client (conditionally required)
  - `{rpc.method}` SERVER: rpc.call.server (conditionally required), rpc.connect_rpc.call.server (conditionally required), rpc.grpc.call.server (conditionally required), rpc.jsonrpc.call.server (conditionally required), rpc.dubbo.call.server (conditionally required)
  - `{gen_ai.operation.name} {gen_ai.request.model}` CLIENT: gen_ai.client.inference (conditionally required), gen_ai.embeddings.client (conditionally required), openai.gen_ai.client.inference (conditionally required), azure.ai.gen_ai.client.inference (conditionally required), anthropic.gen_ai.client.inference (conditionally required), aws.bedrock.gen_ai.client.inference (conditionally required)
  - `{gen_ai.operation.name} {gen_ai.data_source.id}` CLIENT: gen_ai.retrieval.client (conditionally required)
  - `{gen_ai.operation.name}` CLIENT: gen_ai.fetch_response.client (conditionally required), gen_ai.memory.client (conditionally required), openai.fetch_response.client (conditionally required)
  - `create_agent {gen_ai.agent.name}` CLIENT: gen_ai.create_agent.client (conditionally required)
  - `invoke_agent {gen_ai.agent.name}` CLIENT: gen_ai.invoke_agent.client (conditionally required)
  - `invoke_agent {gen_ai.agent.name}` INTERNAL: gen_ai.invoke_agent.internal (conditionally required)
  - `execute_tool {gen_ai.tool.name}` INTERNAL: gen_ai.execute_tool.internal (conditionally required)
  - `invoke_workflow {gen_ai.workflow.name}` INTERNAL: gen_ai.invoke_workflow.internal (conditionally required)
  - `plan {gen_ai.agent.name}` INTERNAL: gen_ai.plan.internal (conditionally required)
  - `execute_tool {gen_ai.tool.name} {gen_ai.skill.name}` INTERNAL: gen_ai.execute_tool.load_skill.internal (conditionally required)
  - `execute_tool {gen_ai.tool.name} {gen_ai.skill.name} {gen_ai.skill.resource.name}` INTERNAL: gen_ai.execute_tool.read_skill_resource.internal (conditionally required)
  - `gen_ai.execute_tool.command.internal` INTERNAL: gen_ai.execute_tool.command.internal (conditionally required)
  - `{mcp.method.name}` CLIENT: mcp.client (conditionally required)
  - `{mcp.method.name}` SERVER: mcp.server (conditionally required)
- Official definition: https://opentelemetry.io/docs/specs/semconv/registry/attributes/error/#error-type
- Link: https://hashspan.dev/learn/otel-attributes/error#error.type

## Which names were renamed or removed?

### `error.message`

- Type: string
- Stability: Deprecated
- Use domain-specific error message attribute. For example, use `feature_flag.error.message` for feature flag errors.
- Examples: `Unexpected input type: string`, `The user has exceeded their storage quota`
- Official definition: https://opentelemetry.io/docs/specs/semconv/registry/attributes/error/#error-message
- Link: https://hashspan.dev/learn/otel-attributes/error#error.message

## FAQ

### Should I set error.type when the operation succeeds?

No. The convention says instrumentations SHOULD NOT set error.type when the operation completed successfully. Its absence is how a query tells success from failure.

### What replaced error.message?

Nothing general. error.message is deprecated: the convention says to use a domain-specific message attribute, such as feature_flag.error.message.

## Read next

- [Span status: Unset, Error, Ok](https://hashspan.dev/learn/otel-span-status)
- [Span events and exceptions](https://hashspan.dev/learn/otel-span-events)
- [Transaction errors explained](https://hashspan.dev/errors)
- [Search every attribute](https://hashspan.dev/learn/otel-attributes.md)

Attribute names, types, stability and descriptions are from the OpenTelemetry semantic conventions, © OpenTelemetry Authors, Apache-2.0.
