Skip to content

Add Span.SetErrorStatus method #5005

@pellared

Description

@pellared

What are you trying to achieve?

During the Logs SIG meeting on 2026-03-10, we discussed whether the tracing API should offer a more ergonomic way to record an operation's final error at the point where the span ends.

One possible direction would be to add an optional error/exception parameter, or a language-appropriate equivalent, to Span.End.

The goal is to make it easier for instrumentation to follow the error recording semantic conventions for spans when the final outcome of the operation is only known immediately before the span is finished.

Today, instrumentation often needs multiple explicit calls to:

  • set error.type
  • set span status
  • call End

This is repetitive, easy to miss, and can lead to inconsistent adoption across languages and instrumentation libraries.

Additional context

This pattern is common in Go instrumentation. For example, OpenTelemetry Go Contrib has code like this:

ctx, span := tracer.Start(ctx, "my-span")
// ...
if err != nil {
	span.SetAttributes(otelsemconv.ErrorType(err))
	span.SetStatus(codes.Error, err.Error())
}
span.End()

With an error-aware End, this could look like:

ctx, span := tracer.Start(ctx, "my-span")
// ...
if err != nil {
	span.End(trace.WithError(err))
} else {
	span.End()
}

Another possible design would be a dedicated convenience method on Span, for example SetErrorStatus(err):

ctx, span := tracer.Start(ctx, "my-span")
defer span.End()
// ...
if err != nil {
	span.SetErrorStatus(err)
}

That shape may be more convenient in languages where End is typically registered at span creation time (for example, defer in Go, using in .NET, or with in Python). It would also fit the existing API style of SetStatus, SetAttributes, and similar mutating methods.

On the other hand, adding a new Span method may be a more disruptive API change in some languages than extending End with optional arguments or options. The tradeoffs may therefore depend on language ergonomics and API stability constraints.

I suspect multiple languages would benefit from a convenience API here, using whatever surface is most idiomatic for that language. This feels analogous to #4824 ("Add optional Exception parameter to Emit LogRecord"), but for tracing.

This is also related to the ongoing discussion about deprecating Span.RecordException:

However, I do not think this should be treated as a direct replacement for Span.RecordException. Recording an exception event and marking a span's final outcome as failed are related but distinct concerns. A convenience API in this area would primarily help instrumentation apply the span error-recording conventions consistently at the end of an operation.

Questions for discussion

  • Should the spec standardize one shape across languages, or only standardize the behavior and let each language choose an idiomatic API?
  • Should this be implemented as SDK functionality, or can it be specified as an API-level helper/default implementation? Adding it at the API layer may reduce flexibility, but it could also allow new functionality without requiring all existing SDK span implementations to change immediately. E.g. if the SDK does not provide native support, then the spec may allow a default implementation that sets attributes and status.
  • Should there an optional parameter to set error.type and maybe also status description if the value calculated by the SDK would not be ideal (like name of the exception type and exception message)?

Tip: React with 👍 to help prioritize this issue. Please use comments to provide useful context, avoiding +1 or me too, to help us triage it. Learn more here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestspec:traceRelated to the specification/trace directory

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions