Skip to content

Error Handling in SDKs, OTLP and the Collector: OTCA practice questions

OpenTelemetry treats telemetry as less important than the application that produces it. The error handling specification states the assumption plainly: users would rather lose telemetry than have the library change how their application behaves. Everything else in this topic follows from that choice.

By Ibrahim Yesilay · Published · Updated

Independent community practice, not affiliated with or endorsed by CNCF or The Linux Foundation.

What Error Handling in SDKs, OTLP and the Collector covers in OTCA

OpenTelemetry treats telemetry as less important than the application that produces it. The error handling specification states the assumption plainly: users would rather lose telemetry than have the library change how their application behaves. Everything else in this topic follows from that choice.

For the API and SDK this means no unhandled exceptions at runtime. API methods must not throw when called incorrectly and should fall back to safe defaults, and the SDK must not throw for failures in its own work, such as an exporter that cannot reach its endpoint. Failing fast is allowed only during initialization, for example on a bad configuration, never later while the application runs. When the library suppresses an error it should log it, and the SDK internal logger level is controlled by OTEL_LOG_LEVEL, which defaults to info. SDKs must also let users register their own error handler, for instance to be strict in a staging environment.

Between an exporter and a receiver, OTLP defines which failures deserve a retry. Over OTLP/HTTP, only 429, 502, 503 and 504 should be retried, and every other 4xx or 5xx must not be; a 400 Bad Request signals permanently bad data. When the server sends a Retry-After header the client should honour it, otherwise it backs off exponentially. Over OTLP/gRPC, codes such as UNAVAILABLE, CANCELLED, DEADLINE_EXCEEDED, ABORTED, OUT_OF_RANGE and DATA_LOSS are retryable, while INVALID_ARGUMENT, PERMISSION_DENIED and UNAUTHENTICATED are not. RESOURCE_EXHAUSTED is retryable only when the server includes RetryInfo. For non-retryable errors the client must drop the data and should count what it dropped.

A successful response can still carry a partial_success field, with a count such as rejected_spans and a human-readable error_message. The client must not retry such a request, since the rest of the data was accepted.

The SDK OTLP exporter has an overall timeout, set through OTEL_EXPORTER_OTLP_TIMEOUT and defaulting to 10 seconds, that covers all attempts and waits for one batch and is not reset per attempt. Transient errors must be retried with exponential backoff and jitter within that budget.

In the Collector, most exporters share exporterhelper settings. The timeout option, 5 seconds by default, applies to each individual send attempt. retry_on_failure backs off from 5 seconds up to 30 seconds with a multiplier of 1.5 and stops after max_elapsed_time. The sending_queue, enabled by default with 10 consumers and room for 1000 requests, buffers data; with block_on_overflow left false, data that does not fit is rejected and shows up in enqueue-failed metrics. Pointing sending_queue.storage at a storage extension such as file_storage moves the queue to disk so it survives restarts.

The memory_limiter processor protects the Collector from running out of memory. Above its soft limit it refuses data with a non-permanent error so that the component in front of it can retry, and above the hard limit it also forces garbage collection. It should be the first processor in a pipeline so that this backpressure reaches the receivers.

Key points

  • OpenTelemetry must not throw unhandled exceptions at runtime; losing telemetry is preferred to disturbing the application.
  • OTLP/HTTP retries only 429, 502, 503 and 504, and a populated partial_success must not be retried.
  • gRPC RESOURCE_EXHAUSTED is retryable only when the server returns RetryInfo.
  • The SDK OTLP timeout defaults to 10s for the whole export, while the Collector exporterhelper timeout of 5s applies per attempt.
  • memory_limiter returns non-permanent errors above its soft limit and belongs first in the processor list.

Three sample questions

8 OTCA questions on Error Handling in SDKs, OTLP and the Collector, 8 with explanations. How practice works

Question 1

Over OTLP/gRPC, a backend answers an export with status RESOURCE_EXHAUSTED and no RetryInfo details. How should the client treat this response?
  1. A.As retryable with exponential backoff, like UNAVAILABLE
  2. B.As a partial success, keeping the accepted part and resending the rest
  3. C.As retryable after exactly 5 seconds, the default OTLP throttling delay
  4. D.As non-retryable, because no RetryInfo signals that it can recover

Correct answer: D

The OTLP spec's gRPC table marks RESOURCE_EXHAUSTED as retryable "only if the server can recover". The client SHOULD treat it as retryable only if the server signals that recovery is possible by returning a status containing RetryInfo (the throttling case, where the client waits the given delay). If no such status is returned, RESOURCE_EXHAUSTED SHOULD be treated as non-retryable. Why the other options are wrong. "As retryable with exponential backoff, like UNAVAI…": UNAVAILABLE is always retryable, but RESOURCE_EXHAUSTED without RetryInfo should be treated as non-retryable. "As a partial success, keeping the accepted part an…": partial success is signalled by a successful response with partial_success populated, not by an error status. "As retryable after exactly 5 seconds, the default…": there is no fixed default delay; with RetryInfo the server supplies the delay, and without it the code is non-retryable.

Sources: OpenTelemetry spec: OTLP protocol, OpenTelemetry spec: OTLP exporter configuration

Question 2

An application's exporter errors are suppressed by the SDK, as the error handling spec requires. Where can an operator see them, and how can the default behaviour be changed?
  1. A.Only in the backend, because the SDK must export its own errors as spans
  2. B.In the SDK internal log (OTEL_LOG_LEVEL) or via a custom error handler
  3. C.Nowhere, because the SDK must hide errors and cannot be configured otherwise
  4. D.In exceptions thrown at runtime once OTEL_LOG_LEVEL is set to debug

Correct answer: B

The error handling spec says that whenever the library suppresses an error that would otherwise reach the user, it SHOULD log it using language-specific conventions, and SDKs MUST let end users change the default error handling, for example to run strictly in staging. The SDK environment variable spec defines OTEL_LOG_LEVEL (default "info") as the log level of the SDK internal logger used for self-diagnostics. Why the other options are wrong. "Only in the backend, because the SDK must export i…": self-diagnostic telemetry is encouraged but optional; the required behaviour is logging the suppressed error. "Nowhere, because the SDK must hide errors and cann…": the spec requires that users can change the default error handling, and suppressed errors SHOULD be logged. "In exceptions thrown at runtime once OTEL_LOG_LEVE…": OTEL_LOG_LEVEL changes the internal logger level; the SDK still must not throw unhandled exceptions.

Sources: OpenTelemetry spec: Error handling, OpenTelemetry spec: SDK environment variables

Question 3

An OTLP/gRPC exporter sends a batch and the server returns INVALID_ARGUMENT because the request contains data it cannot process. What does the OTLP spec require from the client?
  1. A.Retry the same batch with exponential backoff until max_elapsed_time
  2. B.Split the batch in half and resend both halves until one is accepted
  3. C.Drop the data without retrying, and it SHOULD count the dropped data
  4. D.Fall back to OTLP/HTTP on port 4318 and resend the same request there

Correct answer: C

The OTLP spec says non-retryable errors (for example bad data that cannot be deserialized or processed) mean the client MUST NOT retry sending the same data and MUST drop it, and it SHOULD maintain a counter of such dropped data. INVALID_ARGUMENT is the code the server is recommended to use for non-retryable errors and is marked "No" in the retryable table. The OTLP exporter spec limits automatic retries to transient errors. Why the other options are wrong. "Retry the same batch with exponential backoff unti…": backoff retries are for retryable codes such as UNAVAILABLE; INVALID_ARGUMENT MUST NOT be retried. "Split the batch in half and resend both halves unt…": the spec defines no splitting behaviour; the data MUST be dropped. "Fall back to OTLP/HTTP on port 4318 and resend the…": the problem is the data, not the transport; the spec requires dropping it, not resending it.

Sources: OpenTelemetry spec: OTLP protocol, OpenTelemetry spec: OTLP exporter configuration

Practice this topic

Focus mode keeps every question on Error Handling in SDKs, OTLP and the Collector until you leave it. 10 free guest answers, then a free account; no credit card.

Or open OTCA practice across all topics.

Sources

The explanation above was checked against these official documents.

Frequently asked questions

Can an SDK crash my application on bad configuration?

The spec allows failing fast at initialization because of bad user configuration or environment, but the SDK must not make the application fail later at runtime.

Does a rising send-failed metric mean data was lost?

Not by itself. Failed sends may still be retried, so it indicates network or backend trouble; loss occurs when retries are exhausted or the queue rejects data.