Repository navigation
fix(schema): keep an unset column default unset instead of stringifying it - #15225
Lesereingrape wants to merge 1 commit into
Conversation
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: langflow-ai/langflow/.coderabbit.yaml Review profile: CHILL Plan: Advanced Run ID: 📒 Files selected for processing (2)
Included review availability: Your plan provides up to 10 included reviews per hour; 8 remain after this review. Walkthrough
ChangesColumn default handling
Priority: ➖ Normal Estimated code review effort: 2 (Simple) | ~10 minutes Change: Bug fix · Severity of issue fixed: Medium 🚥 Pre-merge checks | ✅ 8 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (8 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
…out one (langflow-ai#16144) fix(schema): keep an unset column default unset instead of stringifying it Column.set_formatter_from_type ran str() on a None default, so a column with no default reached the frontend as the string "None" and the table editor prefilled new rows with it. Return early when the default is None. Declared defaults keep their current normalization. Ported from langflow-ai#15225. Adds tests for an explicit formatter and for the TableInput template path. Co-authored-by: Lengshuang <[email protected]>
) * chore: bump release versions to 1.12.9 * fix: backport 1.13.1 fixes and image security updates to 1.12.9 (#16119) * fix: backport 1.13.1 security and bug fixes to 1.12.9 * fix: repair CI for the 1.12.9 backport * fix: settle discarded browser requests in backport CI * fix: address backport review findings * test: bind background service fixtures to their database * fix: address backport feedback and CI compatibility * fix: absorb lxml and Mako image workarounds for 1.12.9 (#16123) * fix: build lxml with system libraries and require patched Mako * fix: enforce and verify system-linked lxml builds * chore: bump release versions to 1.13.2 * fix: preserve base image dependencies in extension checks * ci: centralize Chromium runner defaults on Ubuntu 24.04 (#16155) ci: pin Chromium workflow defaults to Ubuntu 24.04 * fix: authenticate starter project MCP clients in auto-login mode (#16151) * fix: authenticate starter project MCP clients in auto-login mode * fix: keep starter MCP credentials scoped to the owner * fix: reuse and repair starter MCP owner credentials * fix: preserve document identities during knowledge base ingestion (#16134) * fix: preserve document identities during knowledge base ingestion * [autofix.ci] apply automated fixes * fix: guard ingestion lookups and document upgrade behavior * docs: separate stable ingestion IDs from storage removal notes --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: preserve loop items and distinct outputs in list inputs (#16147) * fix(loop): preserve other sources alongside loop items * fix(graph): resolve each list entry through its source output --------- Co-authored-by: Mart22052006 <[email protected]> * fix: honor detected Windows-1254 text encoding (#16149) * fix: enforce flow permissions for event access (#16150) * fix: enforce flow permissions for event access * test: cover shared flow event permissions * fix: run knowledge base rollback off the event loop (#16148) * fix: run knowledge base rollback off the event loop * fix: preserve queued knowledge base rollback on cancellation * fix: preserve numeric column types in Parser templates (#16146) * fix: preserve numeric column types in Parser templates * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * fix: retain Parser missing-value formatting * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * fix: preserve Parser missing values without slicing every row --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: honor MCP flow visibility for project resources (#16127) * fix: honor MCP flow visibility for project resources * test: document MCP resource visibility cases * ci: pin PR frontend tests to Ubuntu 24.04 * ci: align reusable and manual runner defaults * test: document legacy MCP visibility and isolate CI runner changes * fix: validate class pattern attributes (#16126) * fix: validate class pattern attributes * fix: require explicit attributes in class patterns * ci: pin PR frontend tests to Ubuntu 24.04 * ci: align reusable and manual runner defaults * fix: explain saved flow class pattern restrictions * docs: explain saved flow class pattern migration --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: erichare <[email protected]> * fix: enforce outbound request policy for OpenAPI agents (#16125) * fix: enforce outbound request policy for OpenAPI agents * test: ensure OpenAPI request protection runs in CI * ci: pin PR frontend tests to Ubuntu 24.04 * ci: align reusable and manual runner defaults * fix: bound OpenAPI request timeouts and isolate CI runner changes --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: erichare <[email protected]> * fix: validate MCP shell wrapper arguments consistently (#16124) * fix: validate MCP shell wrapper arguments consistently * test: align MCP runtime rejection with shell policy * fix: exclude keyword assignment mode from MCP shell wrappers * ci: pin PR frontend tests to Ubuntu 24.04 * ci: align reusable and manual runner defaults * fix: restrict MCP shell modes and explain inline command requirements * docs: document MCP shell configuration migration * test: align MCP shell fixtures with restricted modes * fix: authenticate project MCP clients in auto-login mode (#16186) * fix: allow first ingestion into a new OpenSearch index (#16171) * fix: prevent Docker latest tag rollback * fix: prevent Docker latest tag rollback * fix: patch release 1.12.10 image vulnerabilities (#16201) * fix: patch Brotli and image dependencies for 1.12.10 * fix: protect Brotli decoder precedence across interpreters * fix(lfx): apply Split Text Text Key to lists of Data records (#16164) * fix(lfx): apply Split Text's Text Key to lists of Data records Messages keep their own text, and records keep their own key under the default Text Key. * fix(lfx): keep each chunk as Split Text's output text A leftover text field in the source record no longer replaces the chunk. * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Co-authored-by: Olayinka Adelakun <[email protected]> Co-authored-by: Olayinka Adelakun <[email protected]> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix: patch bundled npm glob and minimatch for 1.12.10 (#16205) * chore(release): bump version to 1.12.10 * fix(deps): update FastMCP to 3.4.10 * fix: harden release 1.13.2 image dependencies (#16196) * fix: harden release 1.13.2 image dependencies * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * fix: enforce patched release dependency floors * docs: explain release security guards * fix: protect Brotli decoder precedence across interpreters --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * fix(lfx): report input length and format in Batch Run metadata (#16152) * fix(lfx): report the input length in Batch Run metadata * fix(lfx): add input_format to Batch Run metadata and clarify tooltips Tests cover TOML mode and failure paths; regenerates the component index and starter project. * chore: auto-bake note keys and regenerate backend locales/en.json [skip ci] * [autofix.ci] apply automated fixes --------- Co-authored-by: Raphael Fakhri <[email protected]> Co-authored-by: Olayinka Adelakun <[email protected]> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Olayinka Adelakun <[email protected]> * fix: preserve integer IDs in Parser Stringify tables (#16214) * fix: use namespace-scoped Docker Hub tag API * fix(schema): stop sending "None" as the default of table columns without one (#16144) fix(schema): keep an unset column default unset instead of stringifying it Column.set_formatter_from_type ran str() on a None default, so a column with no default reached the frontend as the string "None" and the table editor prefilled new rows with it. Return early when the default is None. Declared defaults keep their current normalization. Ported from #15225. Adds tests for an explicit formatter and for the TableInput template path. Co-authored-by: Lengshuang <[email protected]> * fix: validate forwarded prefixes as URL paths (#16242) * fix: scope frozen vertex results to the build caller (#16239) * fix: scope frozen vertex results to the build caller * fix: forward build callers through flow execution * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) --------- Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> * test(security): cover reflective namespace laundering (#16243) * test(auth): cover trusted proxy credential sources (#16238) * test(auth): cover trusted proxy credential sources * test(auth): verify WebSocket query token forwarding * fix(decisions): follow the error action for oversized inputs from every provider An input over a decision model's token limit stopped the run even with Evaluation Error Action set to Route to Else, because Langflow only recognised HTTP 413 or a 400 whose error.code is max_tokens_exceeded or context_length_exceeded. None of the three providers answers that way: - OpenAI: 400, code null, "Decision input exceeds the token limit." - TypeSafe: 400 {"detail": {"error_type": "max_tokens_exceeded"}} - Perplexity: 400, code "400", "Decision question requires N tokens with context, exceeding maximum context length (M)" TypeSafe's detail.error_type is now read as a code. OpenAI and Perplexity name no code, so their own fixed sentence is matched, and only as the whole message: a message that quotes the input can't pass for one. The error reference also showed Perplexity's code when it only repeated the status ("HTTP 400, 400"); it now names the provider's type instead ("HTTP 400, invalid_request"). Fixes LE-3117 F1 and F2. * fix(decisions): say on the node that Decision Model needs a Context A Decision Model with Context empty failed at run time with "Enter a Context, or connect a Structured Context.", but nothing on the node said Context was needed: Decision Model and Question carry the required marker, Context did not. Context can't be marked required: a connected Structured Context replaces it, and the editor's required-field check can't see that connection, so it would block valid flows. The field now says so where the user looks instead: its placeholder reads "Required, or Structured Context", and its tooltip ends with "Required unless a Structured Context is connected." The tooltip keeps its purpose first because it is also the argument description an Agent reads in Tool Mode. Fixes LE-3117 F3. * fix(decisions): stop using a decision model switched off in Model Providers Switching a decision model off only hid it from the picker. A field that already named it kept it, marked Switched off, and the flow still sent its messages to that provider. Templates opened with a switched-off jev-latest selected. A decision model sends the flow's messages to its provider, so: - The editor clears a saved decision model that is switched off: its provider is set up and lists the model, but the field no longer offers it. It never picks another model in its place, so messages never go to a provider the user didn't choose. A model whose provider has no key yet, or that policy no longer offers, is kept and explained as before. - A run refuses a model the user switched off: "gpt-6-luna is switched off in Model Providers. Turn it on there, or pick another Decision Model." Only an explicit switch-off counts, so a key sent with the request still works without setup, and standalone lfx, which keeps no settings, is unchanged. - An empty field now asks "Pick a Decision Model." instead of "Pick one". Fixes LE-3117 F4. * fix(i18n): translate the Smart Router and Decision Model fully With the interface in any language but English, the Smart Router showed its name, Input, Routes and Include Else Output translated, and its description, Routing Mode, Decision Model, Decision Type, Decision Question, Minimum Probability, Evaluation Error Action and every decision-mode field in English. The Decision Model had no translations at all. - Adds the 55 missing Smart Router and Decision Model strings to de, es, fr, ja, pt and zh-Hans, and 63 to ko, until the Globalization Pipeline sync supplies them. - Relabels Routes, Include Else Output and Additional Instructions where the old label disagreed with the field names the new tooltips use (e.g. ja 経路 -> ルート, fr Itinéraires -> Routes). - "Open table" stayed English on every table field: each TableInput sends that English default, which overrode the translated label. The default now gives way to the translation; a component's own text is kept. The translations themselves read as a restaurant table in six languages ("Tisch reservieren", "Mesa libre") and now say Open table. Dropdown option values (Decision Model, Choice, Stop with error) are stored values, not labels, and stay as they are. Fixes LE-3117 F5. * fix(frontend): create one flow on a repeated New Flow click (#16232) * fix(agents): keep parallel tool results on their own run (#16233) * fix(api): recover milestones a slow event stream dropped (#16234) * fix(components): send If-Else message on default route (#16275) At Max Iterations the router switches to the default route, but the output methods still picked their message from the original condition, so the default branch ran with an empty message. Both outputs now resolve the active route after the iteration helper runs. * fix(decisions): cover dynamic translations and isolate switch tests * fix: make model provider sections collapsible (LE-3358) (#16281) fix: make model provider sections collapsible * fix(security): reject frozen and ZIP loader imports (#16282) * fix(security): reject frozen and ZIP loader imports * test(security): keep stdlib boundary fixtures importable * fix: apply connector URL policy before connecting to NextPlaid (#16283) * fix: apply connector URL policy before connecting to NextPlaid * fix: refuse unvalidated NextPlaid SDK redirects * fix: require owner credentials for every webhook run (#16284) * fix: require owner credentials for every webhook run * docs: qualify the webhook authentication change by version * fix(authz): refuse unavailable configured plugins (#16286) * fix(serve): scope durable workflow operations to caller (#16287) * fix(security): reject unsafe library execution sinks (#16289) * fix(security): reject unsafe library execution sinks * fix(security): reject mutable template sandbox constructors * fix(security): block Jinja extension constructor re-export * fix: enforce credential destinations during provider validation (#16290) * fix: enforce credential destinations during provider validation * fix: validate gateway destinations before OpenAI key checks * fix: keep public API Request destinations fixed (#16291) * fix: keep public API Request destinations fixed * fix: reject public API Request tool destinations * fix(deps): dependency upgrades for 1.13.2 (#16169) * fix(deps): dependency upgrades for 1.13.2 * fix(deps): require adm-zip 0.6.1 in frontend * fix(deps): require markdown 3.11.2 on Python 3.11+ * chore(deps): drop brotli constraints already in release-1.13.2 * fix(deps): remove ineffective markdown security bump * fix(deps): require OAuthLib 4.0.1 for device-code validation * fix(deps): upgrade AG2 to 1.1.1 in the optional extra * fix(deps): use Tornado 6.6 on Python 3.11 and newer * fix(models): clear rejected Bedrock sampling fields before retrying (#16298) * fix: revoke refresh sessions on logout (#16293) * fix(auth): revoke native refresh tokens on logout * fix(auth): consume refresh tokens by canonical identity * fix: coordinate browser refresh token exchanges * fix: revoke login sessions without consuming refresh tokens * docs: clarify legacy refresh session migration * fix: require a fresh sign-in for legacy refresh tokens * fix: prevent refresh from recreating expired login sessions * fix: scope refresh sessions to active account owners * test: cover logout revocation storage failures * ci: collect flattened single-shard Playwright reports * fix(tracing): isolate concurrent Phoenix workflows (#16294) * fix(tracing): isolate Phoenix LangChain spans across concurrent workflows LangChainInstrumentor is a process-wide singleton, so instrumenting it per workflow routed every concurrent workflow's spans to whichever provider registered first, and uninstrumenting on one workflow's teardown removed instrumentation while other workflows were still running. Build a per-workflow OpenInference LangChain callback bound to the tracer's own provider and hand it to the run through get_langchain_callback instead. Fixes #15555 * test(tracing): assert duplicate Phoenix spans across projects * test(tracing): reject unexpected Phoenix projects * fix(tracing): preserve workflow callbacks across component execution * [autofix.ci] apply automated fixes * [autofix.ci] apply automated fixes (attempt 2/3) * fix(packaging): version Phoenix callback bundle fixes * fix(packaging): align Enterprise profile with bundle versions * fix(tracing): repair isolated callback CI checks * docs(tracing): address CodeRabbit review feedback --------- Co-authored-by: yu1128-L <[email protected]> Co-authored-by: TT <12365@566> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: erichare <[email protected]> * fix(serialization): sanitize nonfinite NumPy and pandas floats (#16297) * fix(serialization): sanitize nonfinite NumPy and pandas floats * fix(serialization): sanitize NumPy object arrays * fix(deps): use patched Zod in the docs toolchain (#16299) fix(deps): update Puppeteer to use patched Zod in docs * fix: recheck execution identity and tool approval at runtime (#16292) * fix(security): recheck runtime tool authorization * test: use native users in component persistence integration tests * test: account for lifecycle reads in workflow query budgets * fix: preserve local and synchronous tool execution * fix: declare synchronous validation in the auth service protocol * fix(security): require admin custom-code authoring by default (#16288) * fix(security): require admin custom-code authoring by default * fix: preserve projects under the default code policy * test: scope trusted code fixtures under the administrator default * test: update remaining trusted authoring and execution fixtures * test: bind an administrator for the standalone REPL tracing test The tracing callback test added in #16294 runs the Python REPL tool with no bound principal. Under the administrator-only custom-code default that call is rejected, so bind an explicit administrator for the test. --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: erichare <[email protected]> * fix(lfx): keep non-string text values in Message (#16218) Message.model_post_init treated every non-string text value as a stream, so a number, dict or list was removed from data and parked in _text_stream. message.text still showed the value, but data["text"], the JSON output, to_lc_message() and Type Convert all saw an empty string. Only iterators and async iterators are streams now. Other non-string values are converted to text. * fix(api): rename a flow that loses a concurrent create for its name (#16302) Flow creation picks a free name with a read and only then inserts, so two POST /api/v1/flows/ calls for the same name from one user both read "free" and the loser hit the unique constraint, surfacing as 400 "Name must be unique" for a name the caller never insisted on. The same window exists for the endpoint name. create_flow now starts the create over when the insert loses that race, so the loser gets the next free suffix exactly as a sequential create does. The retry rolls the transaction back rather than using a savepoint: on SQLite a savepoint that opens the transaction commits on release, and on PostgreSQL the failed insert dooms the transaction. A colliding caller-supplied id is not retried, and callers that pass fail_on_name_conflict / fail_on_endpoint_conflict are untouched. Because the retry rolls back, MCP credentials carried by the flow are now extracted once and staged inside each attempt, as update_flow and upsert_flow already do, so a retried create cannot reference a variable that was never stored. * fix(graph): give list inputs the same value order in every process (#16285) Graph._build_edges collected edges in a set. Edge hashes come from strings, so the set's order followed PYTHONHASHSEED, and a list input fed by several components got its values in a different order after a restart or on another instance. Collect the edges in a dict instead. It drops duplicates the same way and keeps the flow's edge order. Fixes #16110 * fix: stop Filter Values crashing on ordinary text filters (#16202) Filter Values read `.text` on its Filter Key and Filter Value inputs. In a graph run these are plain strings, so every run raised AttributeError, including runs with the default values. Read both inputs through a small helper: use `get_text()` for Data and Message, map None to "", and convert other values to str. A connected Data whose text is a number now matches too. Regenerate the component index entry and add focused tests. Fixes #15729 Co-authored-by: Eric Hare <[email protected]> * fix(lfx): keep top-level JSON arrays in JSON Cleaner (#16206) * fix(lfx): keep top-level JSON arrays in JSON Cleaner JSON Cleaner always cut its input from the first "{" to the last "}". A top-level array lost its brackets: '[{"a": 1}]' came back as a single object, '["x", "y"]' raised "Missing '{' or '}'", and enabling Validate JSON on '[{"a": 1}, {"b": 2}]' failed with "Extra data". Take the outermost JSON value instead: use the array span when it encloses the object span (or there is no object), otherwise the object span as before. * fix(lfx): skip bracketed labels before JSON arrays --------- Co-authored-by: Eric Hare <[email protected]> * fix: reset model provider scroll on selection (#16314) * docs: clarify 1.13.2 upgrades and project authentication (#16318) * docs: fix upgrades from 1.11.x full installations * docs: explain project MCP and A2A authentication defaults * chore: auto-bake note keys and regenerate backend locales/en.json [skip ci] * fix(amazon): address Bedrock Converse QA failures (#16326) * fix(amazon): address Bedrock Converse QA failures * chore: auto-bake note keys and regenerate backend locales/en.json [skip ci] --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> * feat(frontend): let a deployment block the new-project and Deploy buttons with a reason (#16328) * fix(settings): allow custom General sections and profile controls (#16324) * fix: bump 1.14 bundles for merged release fixes * fix: bump Amazon bundle for 1.13.2 Bedrock fixes * feat: create connections inline and inspect trigger payload fields (#16332) Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: erichare <[email protected]> * feat: enable tool mode for dedicated integration actions (#16315) * feat: enable tool mode for dedicated integration actions * feat: enable tool mode for Telegram actions * chore: auto-bake note keys and regenerate backend locales/en.json [skip ci] * fix: gate Valkey vector store on Python 3.15 * fix: align tool mode bundle release metadata * test: synchronize Redis fixtures after maintenance admission * Revert "test: synchronize Redis fixtures after maintenance admission" This reverts commit f641273. --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: erichare <[email protected]> * fix: enforce deployment variable readiness at runtime (#16334) * fix: enforce deployment variable readiness at runtime * chore: auto-bake note keys and regenerate backend locales/en.json [skip ci] * fix: address deployment variable review findings * [autofix.ci] apply automated fixes --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: erichare <[email protected]> * fix(api): accept a new session_id on the advanced run endpoint (#16295) * fix(api): accept a new session_id on the advanced run endpoint * fix(api): skip the cached-graph policy check on a cache miss * docs(api): describe session_id on the advanced run endpoint * fix(frontend): mark sidebar triggers and drop the grip icon (#16278) * fix(api): apply run tweaks after resuming a paused run (#16296) * fix(api): apply run tweaks after resuming a paused run * docs(api): scope the resume tweak comment to background runs * fix(frontend): name playground chat attachments (#16277) * fix(frontend): name playground chat attachments * fix(frontend): name shared-playground files and delete buttons * feat(triggers): enforce governance and report delivery health (#16333) * feat(triggers): enforce governance and report delivery health * fix: gate Valkey vector store on Python 3.15 * chore: auto-bake note keys and regenerate backend locales/en.json [skip ci] * fix(triggers): defer governance imports during service bootstrap * chore: auto-bake note keys and regenerate backend locales/en.json [skip ci] --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: erichare <[email protected]> * fix: preserve Gunicorn compatibility cap in release installs * fix: merge trigger governance and refresh session migrations * fix: refresh Smart Router starter project code * fix(ci): align release tests with current behavior --------- Co-authored-by: Eric Hare <[email protected]> Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com> Co-authored-by: Mart22052006 <[email protected]> Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: erichare <[email protected]> Co-authored-by: olayinkaadelakun <[email protected]> Co-authored-by: Olayinka Adelakun <[email protected]> Co-authored-by: Olayinka Adelakun <[email protected]> Co-authored-by: Raphael Fakhri <[email protected]> Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com> Co-authored-by: Viktor Avelino <[email protected]> Co-authored-by: Lengshuang <[email protected]> Co-authored-by: Cristhian Zanforlin Lousa <[email protected]> Co-authored-by: Adam-Aghili <[email protected]> Co-authored-by: yu1128-L <[email protected]> Co-authored-by: TT <12365@566> Co-authored-by: Mohammad Hijjawi <[email protected]>
References
Fixes #15224
Changes
Column.defaultis typedstr | bool | int | float | None, butset_formatter_from_typeended every non-boolean case inself.default = str(self.default)— including whendefaultwas stillNone. Sincestr(None) == "None", a column declared without a default stopped meaning "no default" and started carrying the four-character stringNone, which then went out in the serialized table schema ("default": "None").This adds an early return for the unset case, before any coercion:
@model_validator(mode="after") def set_formatter_from_type(self): if self.type and not self.formatter: self.formatter = self.validate_formatter(self.type) + if self.default is None: + # ``None`` means "no default". Coercing it below would send the literal string "None" to the + # frontend, where the table editor prefills new rows with it. + return self if self.formatter in {"boolean", "bool"}:Four production lines, no other branch touched. The frontend already treats a null default as the normal state —
TableNodeComponent/index.tsx:139prefills a new row withcolumn.default ?? null, andutils.ts:680generates columns withdefault: null— so this makes the backend agree with the contract the UI is already coded against instead of introducing a new one.How was this tested
makeis not available on this machine, so I ran the underlying command of the package's ownmake testtarget (src/lfx/Makefile:46isuv run --package lfx pytest tests -v) directly fromsrc/lfx:--no-synckeeps the shared workspace venv in the lfx-only state; without ituv runre-resolves the whole workspace and reinstallslangflow, which trips the guard atsrc/lfx/tests/conftest.py:39("langflow is installed. These tests require langflow to NOT be installed").Against
main@5621dcfdwith only the new tests added, the change is required — 11 failed, 15 passed:With the fix in place: 26 passed.
booleanis deliberately one of the 15 that already passed — that branch never stringifiedNone, which is why the bug was inconsistent across formatters rather than uniform.Three new tests were added in a new
TestColumnDefaultclass in that existing file (17 cases once parametrized):test_unset_default_stays_none— all 11 declared type spellings (text/str/string/integer/int/float/number/boolean/json/date, and notypeat all).test_unset_default_does_not_serialize_as_the_string_none— asserts onTableSchema.model_dump()and on thejson.dumpsof it, so a regression has to break the wire format, not just the attribute.test_provided_defaults_are_normalized_as_before— pins the pre-existing normalization for values that are set (30 → "30",1.5 → "1.5","true" → True,False → False), which is what proves this PR changes the unset case only.The reproduction snippet from the linked issue was re-run against the change and prints
None/"default": null.The wider
tests/unit/schemadirectory was also run with the fix in place: 359 passed, 1 skipped, plus 4 errors that are this Windows machine's filesystem permissions intest_image.py(PermissionErrorunder%LOCALAPPDATA%); that file contains no reference toColumn, so those are environment noise rather than regressions. I did not run the entirelfxsuite as part of this change, and CI covers it.ruff format --diffandruff checkboth report clean on the two changed files.What else to consider
elif self.formatter in {"integer", "int"}andelif self.formatter in {"float"}, and both are unreachable:validate_formatteralready mapsinteger/int/floatontoFormatterType.number, so the comparisons never match and numeric defaults fall through tostr(). That is arguably a second bug, but fixing it would change30from"30"to30on the wire, and two existing tests pin the current behaviour (src/backend/tests/unit/components/data_source/test_table_loader_component.py:223,...test_table_schema_demo_component.py:184). Making a column's default an actual number is a product decision about the frontend contract, not a mechanical cleanup, so it belongs in its own issue rather than smuggled in here.Column— the in-repo users are thetable/load_from_dbtest components and user-authored custom components, which import it as public schema (from lfx.schema.table import Column). So the practical blast radius is custom components with table inputs, not the built-in gallery.Column.defaultwere checked rather than assumed: every one of them passes an explicit non-Nonedefault, and no test anywhere assertsdefault == "None", so the early return cannot contradict them.column/formatterhits were#6775about dataframe add-column input and#4774about Filter Data), and no open issue reports this.Attribution: this change was prepared by an AI coding agent working from the account holder's instruction, and has not been reviewed by a human before opening. The RED/GREEN numbers above are measured output, not estimates.
Summary by CodeRabbit
Bug Fixes
"None"as a prefilled value when a column default is unset.null, while explicitly provided defaults retain their existing behavior.Tests