Span status: when is a span an error?

3 min read

Short answer

A span's status is Unset, Error or Ok. Unset is the default and means the operation finished without an error. Instrumentation sets Error when the operation failed, together with an error.type attribute that names the class of error. Ok is for a developer or operator who wants to mark success explicitly.

On this page

In my demo run, the agent’s withdraw_from_vault tool span has no error. The transaction it sent reverted. Both spans are right, because they describe different operations.

Span status in one agent run: the tool span and the send span are Unset, while the confirm span of the reverted transaction is Error with error.type reverted.

What are the three status codes?

Code Means Who sets it
Unset Finished without an error. The default. Nobody, it’s what you get
Error The operation failed Instrumentation, when it fails
Ok Explicitly marked successful An application developer or operator

The semantic conventions say instrumentation must leave status Unset when an operation ends without errors (recording errors). So most healthy spans are Unset, not Ok. That surprises people who look for a green “Ok” in their backend.

Error status comes with error.type

When an operation fails, instrumentation sets status Error and the error.type attribute. error.type is stable and names the class of error, such as timeout. It should have low cardinality, so put the details somewhere else.

import { SpanStatusCode, type Span } from '@opentelemetry/api';
function endConfirm(span: Span, receipt: { status: 'success' | 'reverted' }) {
span.setAttribute('blockchain.tx.status', receipt.status);
if (receipt.status === 'reverted') {
span.setAttribute('error.type', 'reverted');
span.setStatus({ code: SpanStatusCode.ERROR });
}
span.end();
}
confirm 8453 UNSET { 'blockchain.tx.status': 'success' }
confirm 8453 ERROR { 'blockchain.tx.status': 'reverted', 'error.type': 'reverted' }

Whose error is it?

Status belongs to the operation the span describes, not to the whole trace. Here’s the run:

withdraw_from_vault · from make demodurations from the run; positions approximate
execute_tool withdraw_from_vault262.7 ms262.7 ms
send 313374.4 ms4.4 ms
confirm 31337264.9 ms264.9 ms
The tool returned normally, so its span is Unset. The confirm span is Error. It ends after the tool because it stays open while the revert reason is fetched; the tool got the receipt before that.
  • send is Unset. Sending worked: the node accepted the transaction and returned its hash.
  • confirm is Error. The receipt says the transaction reverted.
  • execute_tool is Unset. viem returned the receipt without throwing, and the tool passed { status: "reverted" } back to the model. Nothing failed inside the tool.

You could argue the tool span should be Error too. I don’t think so: the tool did its job and told the agent the truth. The failure is real, and it’s on the span that describes it. Filter on error.type in your backend and you find it. This post shows what you’d see without that span.

FAQ

When should a span have status Error?

When the operation it describes failed. Errors that were retried or handled, so the operation still completed, shouldn't mark the span as an error.

What is error.type in OpenTelemetry?

A stable attribute that names the class of error the operation ended with, such as a status code or an exception class. It should have low cardinality. _OTHER is the fallback when the instrumentation has no better value.

Should I set status Ok on successful spans?

Instrumentation libraries should leave status Unset on success. Ok is a final call by an application developer or operator, and it can't be overridden by a later Error.

Go further

Type to search the docs, Learn topics and the blog.