Skip to content

Span.set_status: a bare Status(ERROR) replaces an existing Status(ERROR, description) and drops the description #5661

Description

@WatchTree-19

Describe your environment

opentelemetry-sdk 1.44.0, CPython 3.11. Also present at main (opentelemetry-sdk/src/opentelemetry/sdk/trace/__init__.py, Span.set_status).

What happened?

set_status guards two cases when it is handed a Status instance: it returns early if the span is already OK, and it returns early if the incoming status is UNSET. Nothing guards a second ERROR overwriting a first one, so self._status = status runs unconditionally and a bare Status(StatusCode.ERROR) with no description silently replaces Status(StatusCode.ERROR, "..."). The status code is unchanged, so nothing looks wrong; only the description disappears.

This is reachable without anyone doing something odd. A library sets a specific error on a span, and later generic error handling, exception bookkeeping or an instrumentation helper sets a plain ERROR on the same span. The specific message is the one that had diagnostic value, and it is the one that is lost.

Steps to reproduce

from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.trace import Status, StatusCode

span = TracerProvider().get_tracer(__name__).start_span("demo")
span.set_status(Status(StatusCode.ERROR, "connection refused to db-1"))
span.set_status(Status(StatusCode.ERROR))

print(span.status.description)

What did you expect to see?

connection refused to db-1.

What did you see instead?

None.

Suggested fix

In the isinstance(status, Status) branch, decline the assignment when the incoming status carries no description and the existing status has the same code and does have one. That keeps the first, more specific description without changing the status code, and it leaves every other transition alone, including a genuine re-description of an existing error.

It is a small change and I have it written, so a PR will follow this issue rather than wait on agreement. If maintainers would rather the precedence sat somewhere else, or would rather it not change at all, say so there and I will rework or close it.

Additional context

This surfaced from open-telemetry/opentelemetry-python-contrib#4769, where I first tried to handle it in the shared HTTP semconv helper by reading span.status before setting it. @herin049 pointed out, correctly, that the trace API does not expose a readable status on Span at all, only the SDK's ReadableSpan does, so that fix depended on an implementation detail and put precedence logic in two places that could disagree. Raising it here instead, where set_status already owns precedence.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions