fix(data): prevent empty string from overwriting step content on upsert#2807
Merged
hayescode merged 1 commit intoChainlit:mainfrom Mar 5, 2026
Conversation
When cl.Step initializes, input and output default to empty strings. The create_step SQL uses COALESCE(EXCLUDED.output, "Step".output) on conflict, but COALESCE treats empty string as a valid non-NULL value. If the initial Step.send() (with empty output) commits to the database after Step.update() (with actual content), the empty string overwrites the real content. Wrap EXCLUDED.output and EXCLUDED.input with NULLIF(..., '') so that empty strings are treated as NULL by COALESCE, preserving any existing non-empty content in the database. Fixes #2789
hayescode
approved these changes
Mar 5, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
When using
cl.Step, content within steps occasionally disappears or appears empty when reloading a thread from history. This is caused by a race condition between the initialstep.send()and the subsequentstep.update().cl.Stepinitializesinputandoutputas empty strings (""). InChainlitDataLayer.create_step, the SQL uses:Since empty string is not
NULL,COALESCEaccepts it as a valid value. If the background task for the initialsend()(with empty output) finishes after the finalupdate()(with actual content), the empty string overwrites the content.Fix
Wrap
EXCLUDED.outputandEXCLUDED.inputwithNULLIF(..., ''):This treats empty strings as
NULL, soCOALESCEfalls back to the existing database content.Test
Added
test_create_step_uses_nullif_for_output_and_inputthat verifies the SQL contains theNULLIFprotection.Fixes #2789
Summary by cubic
Prevent empty-string input/output from overwriting step content during upsert. Fixes a race where initial Step.send() could erase content saved by Step.update(), so step content persists when reloading threads.
Written for commit 8095410. Summary will update on new commits.