apache / apache/airflow

Airflow 3 update_xcom_entry is adding unnecessary quotes to the string value

Open
#64,573 9 comments 1 reaction 1 assignee Claimed by @denncs-tx View on GitHub
area:core contributors-workshop kind:bug
Dominant language
Python
Stars
46.9k
Forks
17.8k
Avg merge
2d 9h
Merged PRs (30d)
472

Description

### Apache Airflow version

3.1.8

### What happened and how to reproduce it?

I am using apache-airflow-client==3.1.6 to get/create/update XCOM value. What I see is that

- `create_xcom_entry` works correctly, if a pass a string value, it properly stores that, and `get_xcom_entry` gets back the exact same value.
- `update_xcom_entry` though quotes to the value, so `get_xcom_entry` gets back the value in quotation marks. I see the same on the UI (Browse/XComs)

Code to reproduce the issue:
```python
def reporduce_the_issue():
api_client_provider = AirflowApiClientProvider()
DAG_ID = '_for_testing'
DAG_RUN_ID = 'manual__2026-03-31T12:59:12.433086+00:00'
TASK_ID = 'task1'
XCOM_KEY = random_xcom_key()
XCOM_VALUE1 = 'test_value1'
XCOM_VALUE2 = 'test_value2'

with api_client_provider.get_api_client() as api_client:
xcom_api = airflow_client.client.XComApi(api_client)

log.info('Check that it does not exist yet.')
try:
xcom_api.get_xcom_entry(
dag_id=DAG_ID,
dag_run_id=DAG_RUN_ID,
task_id=TASK_ID,
xcom_key=XCOM_KEY,
)
log.error(f'Random is not random enough, try it again')
return
except NotFoundException:
pass

log.info(f'Create {XCOM_KEY} with value {XCOM_VALUE1}.')
xcom_api.create_xcom_entry(
dag_id=DAG_ID,
dag_run_id=DAG_RUN_ID,
task_id=TASK_ID,
x_com_create_body=XComCreateBody(key=XCOM_KEY, value=XCOM_VALUE1)
)
log.info('Get the value.')
xcom_entry = xcom_api.get_xcom_entry(
dag_id=DAG_ID,
dag_run_id=DAG_RUN_ID,
task_id=TASK_ID,
xcom_key=XCOM_KEY,
)
val = xcom_entry.to_dict().get('value')
log.info(f'Value after creation: {val=}')

log.info(f'Update {XCOM_KEY} with value {XCOM_VALUE2}.')
xcom_api.update_xcom_entry(
dag_id=DAG_ID,
dag_run_id=DAG_RUN_ID,
task_id=TASK_ID,
xcom_key=XCOM_KEY,
x_com_update_body=XComUpdateBody(value=XCOM_VALUE2)
)
log.info('Get the value.')
xcom_entry = xcom_api.get_xcom_entry(
dag_id=DAG_ID,
dag_run_id=DAG_RUN_ID,
task_id=TASK_ID,
xcom_key=XCOM_KEY,
)
val = xcom_entry.to_dict().get('value')
log.info(f'Value after update: {val=}')

```

### What you think should happen instead?

The value should not be changed by the update method. It should not be quoted.

```
2026-04-01 11:43:24,459 - __main__ - INFO - Check that it does not exist yet.
2026-04-01 11:43:24,513 - __main__ - INFO - Create task_ikp517fwfb with value test_value1.
2026-04-01 11:43:24,561 - __main__ - INFO - Get the value.
2026-04-01 11:43:24,590 - __main__ - INFO - Value after creation: val='"test_value1"'
2026-04-01 11:43:24,590 - __main__ - INFO - Update task_ikp517fwfb with value test_value2.
2026-04-01 11:43:24,624 - __main__ - INFO - Get the value.
2026-04-01 11:43:24,652 - __main__ - INFO - Value after update: val='"\\"test_value2\\""'
```

### Operating System

Debian GNU/Linux 12 (bookworm)

### Versions of Apache Airflow Providers

apache-airflow==3.1.8
apache-airflow-client==3.1.6
apache-airflow-core==3.1.8

### Deployment

Docker-Compose

### Deployment details

_No response_

### Anything else?

_No response_

### Are you willing to submit PR?

- [x] Yes I am willing to submit a PR!

### Code of Conduct

- [x] I agree to follow this project's [Code of Conduct](https://github.com/apache/airflow/blob/main/CODE_OF_CONDUCT.md)

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.