> ## Documentation Index
> Fetch the complete documentation index at: https://braintrust.dev/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Null input on spans when using OTEL attributes

export const plans_0 = "Any"

export const deployments_0 = "Any"

export const data_plane_version_0 = undefined

export const use_case_0 = "Use case - Tracing applications sending spans via OTEL where the input field appears null despite data being sent"

<Note>
  **Applies to:**

  * Plan - {plans_0}
  * Deployment - {deployments_0}
  * {data_plane_version_0}
  * {use_case_0}
</Note>

## Summary

**Issue:** Spans ingested through the OpenTelemetry endpoint show `input` as `null` even though the exporter is setting `braintrust.input_json`. The value is preserved on the span under `metadata."braintrust.input_json"` instead of being translated into the span's `input` field.

**Cause:** This happens when the `braintrust.input_json` (or `braintrust.output_json`) attribute fails to parse as JSON. Braintrust translates `braintrust.*` OTEL attributes into native span fields, but if parsing fails the attribute falls back to `metadata` rather than `input` or `output`.

The two parse failure modes are:

* The attribute value is not a string.
* The attribute value is a string but is not valid JSON.

**Resolution:** Ensure the `braintrust.input_json` attribute value is a valid JSON string before sending it via OTEL.

## Diagnosis

### Step 1: Confirm the input was captured in metadata

Run the following query against the affected project, adjusting the time range and any additional filters as needed:

```sql theme={"theme":{"light":"github-light","dark":"github-dark-dimmed"}}
SELECT
  id,
  metadata.'braintrust.input_json'
FROM project_logs('<project_id>') -- Replace with your project ID
WHERE metadata.'braintrust.input_json' IS NOT NULL
  AND created >= NOW() - INTERVAL 1 hour
LIMIT 100
```

Each row returned is a span whose `input` was dropped during ingestion and preserved under `metadata."braintrust.input_json"`.

### Step 2: Validate the captured value as JSON

Copy a sample value from the previous query and pass it through any JSON validator (for example, `python -m json.tool` or `jq .`). If the validator rejects it, the exporter is emitting an invalid JSON string for `braintrust.input_json`, which explains why `input` is null on the span.

The same logic applies to `braintrust.output_json` mapped to `output`, and to `braintrust.expected_json` mapped to `expected`.

## Resolution steps

### Step 1: Fix the exporter to emit valid JSON

Update the instrumentation that sets `braintrust.input_json` so the attribute value is a JSON-serialized string. Common failures to check for:

* Concatenating raw strings instead of running them through a JSON serializer.
* Setting the attribute to a Python `dict`, JavaScript object, or other non-string value. OTEL attribute values must be strings (or other primitive types); non-string complex values get coerced and produce invalid JSON.
* Truncating the attribute value at the OTEL SDK's attribute length limit. Configure the exporter to allow larger attribute values, or send the payload through `braintrust.input.0.role` / `braintrust.input.0.content` flattened attributes instead.

### Step 2: Alternative: use plain `braintrust.input`

If the payload is a single string (for example, a user message), set `braintrust.input` instead of `braintrust.input_json`. The plain `braintrust.input` attribute accepts a raw string and does not require JSON parsing.

For structured inputs like message arrays, you can also set flattened attributes such as `braintrust.input.0.role` and `braintrust.input.0.content`. See the [OpenTelemetry integration reference](/integrations/sdk-integrations/opentelemetry#braintrust-attributes) for the full attribute table.

### Step 3: Verify ingestion

After deploying the exporter fix, re-run the diagnostic query from Step 1. New spans should no longer carry `metadata."braintrust.input_json"`, and the span's `input` field should be populated.

## Relevant links

* [OpenTelemetry integration — Braintrust attributes](/integrations/sdk-integrations/opentelemetry#braintrust-attributes)
* [Advanced tracing](/instrument/advanced-tracing)
* [Strip OTel attributes from metadata](/kb/strip-otel-attributes-from-metadata)
