Skip to content

fix(agentic): guard component code search column input#13620

Open
kiranmagic7 wants to merge 1 commit into
langflow-ai:mainfrom
kiranmagic7:kiran/component-code-search-column-guard
Open

fix(agentic): guard component code search column input#13620
kiranmagic7 wants to merge 1 commit into
langflow-ai:mainfrom
kiranmagic7:kiran/component-code-search-column-guard

Conversation

@kiranmagic7

@kiranmagic7 kiranmagic7 commented Jun 11, 2026

Copy link
Copy Markdown

Summary

Notes

CONTRIBUTING.md says to target the active release branch, but the latest release is 1.10.0 and there is no release-1.10.1 branch currently published. This PR targets main, matching the current bug report surface.

Validation

  • python3 -m json.tool src/backend/base/langflow/agentic/flows/LangflowAssistant.json >/dev/null
  • uv run pytest src/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.py -q — 2 passed
  • uv run ruff check src/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.py
  • git diff --check

Summary by CodeRabbit

Release Notes

  • Bug Fixes

    • Improved search error handling to provide explicit feedback when requested columns are missing, instead of silently returning empty results.
  • Tests

    • Added regression test coverage to validate search tool configuration and error handling behavior.

@coderabbitai

coderabbitai Bot commented Jun 11, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Important

Review skipped

Auto incremental reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: dc854c13-0e2a-45f6-afd2-627da2f5dde3

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Walkthrough

This PR fixes silent failures in the Langflow Assistant's component_code_search tool. The embedded DataFrameKeywordSearch component now raises descriptive errors for invalid columns instead of returning empty results, and the column input is hidden from the model with a sensible default.

Changes

Component Code Search Tool Hardening

Layer / File(s) Summary
DataFrameKeywordSearch component behavior and defaults
src/backend/base/langflow/agentic/flows/LangflowAssistant.json
The component's search() method is updated to raise ValueError with a list of valid columns when the requested column is missing, replacing the previous silent return of an empty DataFrame. The column input removes tool_mode=True so it is no longer a model-supplied argument, and its default value is changed from file_path to text.
Tool schema metadata alignment
src/backend/base/langflow/agentic/flows/LangflowAssistant.json
The tools_metadata entry for component_code_search is updated to reflect the revised component input surface, removing undocumented argument definitions from the tool schema exposed to the agent.
Regression test coverage
src/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.py
New pytest tests validate that the column input is not exposed in the tool arguments and that the search method raises expected errors for unknown columns, preventing regression of this silent-failure behavior.

🎯 2 (Simple) | ⏱️ ~12 minutes

🚥 Pre-merge checks | ✅ 7 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Test Quality And Coverage ⚠️ Warning Tests are structural JSON validation only, not behavioral. They verify configuration but don't execute the component to test actual error handling. Additionally, IntInput is used in code but not im... Add integration tests that instantiate DataFrameKeywordSearch and test search() with unknown column to verify ValueError is raised. Fix IntInput import in LangflowAssistant.json line 2764.
✅ Passed checks (7 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'fix(agentic): guard component code search column input' directly and clearly summarizes the main change: preventing the column input from being exposed to the model by guarding it.
Linked Issues check ✅ Passed All coding requirements from issue #13618 are met: column input tool_mode removed, column pinned to 'text', silent failure replaced with descriptive ValueError, and regression tests added to validate the shipped flow.
Out of Scope Changes check ✅ Passed All changes are directly in scope: the flow JSON update addresses the tool exposure issue, and the test file validates the fix without introducing unrelated modifications.
Test Coverage For New Implementations ✅ Passed PR includes substantive regression tests for bug fix changes. New test file follows naming convention (test_*.py), is properly located in unit/agentic/flows/, uses module-scoped fixture to load act...
Test File Naming And Structure ✅ Passed Test file follows correct patterns: test_*.py format in src/backend/tests/unit/, proper pytest structure with fixtures, descriptive test function names, organized setup/teardown with module-scoped...
Excessive Mock Usage Warning ✅ Passed The test file uses no mocks whatsoever. It loads the real LangflowAssistant.json file and directly inspects its actual structure and content, testing real behavior without mock obscuration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 11, 2026

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/backend/base/langflow/agentic/flows/LangflowAssistant.json`:
- Line 2764: The embedded component DataFrameKeywordSearch uses IntInput (for
number_candidates) but IntInput is not imported from langflow.io, causing a
NameError when the component loads; update the import statement that currently
lists DataFrameInput, MessageTextInput, DropdownInput, BoolInput, Output to also
include IntInput so the class DataFrameKeywordSearch can reference IntInput
without error.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: b9dbcc83-e233-4f7c-bada-9d8715e9d14f

📥 Commits

Reviewing files that changed from the base of the PR and between 3a8f48b and 49b873a.

📒 Files selected for processing (2)
  • src/backend/base/langflow/agentic/flows/LangflowAssistant.json
  • src/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.py

"title_case": false,
"type": "code",
"value": "from langflow.custom import Component\nfrom langflow.io import DataFrameInput, MessageTextInput, DropdownInput, BoolInput, Output\nfrom langflow.schema import DataFrame\nimport pandas as pd\n\n\nclass DataFrameKeywordSearch(Component):\n display_name = \"Keyword Search\"\n description = \"Search for keywords in a DataFrame column using any/all/coverage matching\"\n icon = \"Search\"\n\n inputs = [\n DataFrameInput(\n name=\"dataframe\",\n display_name=\"DataFrame\",\n info=\"Input DataFrame to search\",\n ),\n MessageTextInput(\n name=\"column\",\n display_name=\"Column\",\n info=\"Column name to search in\",\n tool_mode=True,\n ),\n MessageTextInput(\n name=\"keywords\",\n display_name=\"Keywords\",\n info=\"Keywords to search for\",\n is_list=True,\n tool_mode=True,\n ),\n DropdownInput(\n name=\"match_type\",\n display_name=\"Match Type\",\n options=[\"any\", \"all\", \"coverage\"],\n value=\"any\",\n info=\"'any' = OR logic, 'all' = AND logic, 'coverage' = keyword coverage ranking\",\n ),\n BoolInput(\n name=\"case_sensitive\",\n display_name=\"Case Sensitive\",\n value=False,\n advanced=True,\n info=\"Whether search is case-sensitive\",\n ),\n IntInput(\n name=\"number_candidates\",\n display_name=\"Number of Candidates\",\n value=5,\n info=\"The number of candidates to filter and return in the dataframe output\")\n ]\n\n outputs = [\n Output(name=\"result\", display_name=\"Filtered DataFrame\", method=\"search\"),\n ]\n\n def search(self) -> DataFrame:\n df = self.dataframe\n column = self.column\n keywords = self.keywords if isinstance(self.keywords, list) else []\n match_type = self.match_type\n case_sensitive = self.case_sensitive\n\n if df is None or len(df) == 0:\n return DataFrame(pd.DataFrame())\n\n if column not in df.columns:\n return DataFrame(pd.DataFrame())\n\n keywords = [str(k).strip() for k in keywords if k]\n if not keywords:\n return DataFrame(df)\n\n text_series = df[column].fillna(\"\").astype(str)\n\n if not case_sensitive:\n text_series = text_series.str.lower()\n keywords = [k.lower() for k in keywords]\n\n if match_type == \"any\":\n mask = pd.Series([False] * len(df), index=df.index)\n for keyword in keywords:\n mask = mask | text_series.str.contains(keyword, regex=False)\n result = df[mask]\n\n elif match_type == \"all\":\n mask = pd.Series([True] * len(df), index=df.index)\n for keyword in keywords:\n mask = mask & text_series.str.contains(keyword, regex=False)\n result = df[mask]\n\n elif match_type == \"coverage\":\n scores = []\n total_keywords = len(keywords)\n\n for text in text_series:\n keywords_found = sum(1 for keyword in keywords if keyword in text)\n score = keywords_found / total_keywords\n scores.append(score)\n\n result = df.copy()\n result[\"_score\"] = scores\n result = result[result[\"_score\"] > 0].sort_values(\"_score\", ascending=False)\n\n return DataFrame(result.reset_index(drop=True)).head(self.number_candidates)"
"value": "from langflow.custom import Component\nfrom langflow.io import DataFrameInput, MessageTextInput, DropdownInput, BoolInput, Output\nfrom langflow.schema import DataFrame\nimport pandas as pd\n\n\nclass DataFrameKeywordSearch(Component):\n display_name = \"Keyword Search\"\n description = \"Search for keywords in a DataFrame column using any/all/coverage matching\"\n icon = \"Search\"\n\n inputs = [\n DataFrameInput(\n name=\"dataframe\",\n display_name=\"DataFrame\",\n info=\"Input DataFrame to search\",\n ),\n MessageTextInput(\n name=\"column\",\n display_name=\"Column\",\n info=\"Column name to search in\",\n value=\"text\",\n ),\n MessageTextInput(\n name=\"keywords\",\n display_name=\"Keywords\",\n info=\"Keywords to search for\",\n is_list=True,\n tool_mode=True,\n ),\n DropdownInput(\n name=\"match_type\",\n display_name=\"Match Type\",\n options=[\"any\", \"all\", \"coverage\"],\n value=\"any\",\n info=\"'any' = OR logic, 'all' = AND logic, 'coverage' = keyword coverage ranking\",\n ),\n BoolInput(\n name=\"case_sensitive\",\n display_name=\"Case Sensitive\",\n value=False,\n advanced=True,\n info=\"Whether search is case-sensitive\",\n ),\n IntInput(\n name=\"number_candidates\",\n display_name=\"Number of Candidates\",\n value=5,\n info=\"The number of candidates to filter and return in the dataframe output\")\n ]\n\n outputs = [\n Output(name=\"result\", display_name=\"Filtered DataFrame\", method=\"search\"),\n ]\n\n def search(self) -> DataFrame:\n df = self.dataframe\n column = self.column\n keywords = self.keywords if isinstance(self.keywords, list) else []\n match_type = self.match_type\n case_sensitive = self.case_sensitive\n\n if df is None or len(df) == 0:\n return DataFrame(pd.DataFrame())\n\n if column not in df.columns:\n valid_columns = \", \".join(map(str, df.columns))\n raise ValueError(f\"Unknown column {column!r}. Valid columns: {valid_columns}\")\n\n keywords = [str(k).strip() for k in keywords if k]\n if not keywords:\n return DataFrame(df)\n\n text_series = df[column].fillna(\"\").astype(str)\n\n if not case_sensitive:\n text_series = text_series.str.lower()\n keywords = [k.lower() for k in keywords]\n\n if match_type == \"any\":\n mask = pd.Series([False] * len(df), index=df.index)\n for keyword in keywords:\n mask = mask | text_series.str.contains(keyword, regex=False)\n result = df[mask]\n\n elif match_type == \"all\":\n mask = pd.Series([True] * len(df), index=df.index)\n for keyword in keywords:\n mask = mask & text_series.str.contains(keyword, regex=False)\n result = df[mask]\n\n elif match_type == \"coverage\":\n scores = []\n total_keywords = len(keywords)\n\n for text in text_series:\n keywords_found = sum(1 for keyword in keywords if keyword in text)\n score = keywords_found / total_keywords\n scores.append(score)\n\n result = df.copy()\n result[\"_score\"] = scores\n result = result[result[\"_score\"] > 0].sort_values(\"_score\", ascending=False)\n\n return DataFrame(result.reset_index(drop=True)).head(self.number_candidates)"

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

uv run python - <<'PY'
import json
from pathlib import Path

path = Path("src/backend/base/langflow/agentic/flows/LangflowAssistant.json")
flow = json.loads(path.read_text(encoding="utf-8"))

template = None
for node in flow["data"]["nodes"]:
    data = node.get("data", {})
    if data.get("type") == "DataFrameKeywordSearch":
        template = data["node"]["template"]
        break

assert template is not None, "DataFrameKeywordSearch template not found"

code = template["code"]["value"]
import_lines = [ln for ln in code.splitlines() if ln.startswith("from langflow.io import")]
uses_intinput = "IntInput(" in code
imports_intinput = any("IntInput" in ln for ln in import_lines)

print("uses_intinput =", uses_intinput)
print("imports_intinput =", imports_intinput)

if uses_intinput and not imports_intinput:
    raise SystemExit("Mismatch confirmed: IntInput is used but not imported.")
PY

Repository: langflow-ai/langflow

Length of output: 107


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import json
from pathlib import Path

path = Path("src/backend/base/langflow/agentic/flows/LangflowAssistant.json")
flow = json.loads(path.read_text(encoding="utf-8"))

template = None
for node in flow["data"]["nodes"]:
    data = node.get("data", {})
    if data.get("type") == "DataFrameKeywordSearch":
        template = data["node"]["template"]
        break

assert template is not None, "DataFrameKeywordSearch template not found"

code = template["code"]["value"]
import_lines = [ln for ln in code.splitlines() if ln.startswith("from langflow.io import")]
uses_intinput = "IntInput(" in code
imports_intinput = any("IntInput" in ln for ln in import_lines)

print("uses_intinput =", uses_intinput)
print("imports_intinput =", imports_intinput)

if uses_intinput and not imports_intinput:
    raise SystemExit("IntInput is used but not imported in embedded component code.")
PY

Repository: langflow-ai/langflow

Length of output: 190


Fix embedded component: import IntInput in DataFrameKeywordSearch
The embedded Python code uses IntInput(...) but the from langflow.io import ... line omits IntInput, which will raise a NameError when the component is loaded (around line 2764).

Suggested fix
-from langflow.io import DataFrameInput, MessageTextInput, DropdownInput, BoolInput, Output
+from langflow.io import DataFrameInput, MessageTextInput, DropdownInput, BoolInput, IntInput, Output
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/backend/base/langflow/agentic/flows/LangflowAssistant.json` at line 2764,
The embedded component DataFrameKeywordSearch uses IntInput (for
number_candidates) but IntInput is not imported from langflow.io, causing a
NameError when the component loads; update the import statement that currently
lists DataFrameInput, MessageTextInput, DropdownInput, BoolInput, Output to also
include IntInput so the class DataFrameKeywordSearch can reference IntInput
without error.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 11, 2026
@kiranmagic7

Copy link
Copy Markdown
Author

Pushed 92cbb88f51 to address the missing IntInput import noted in review. The bundled component now imports IntInput alongside the other IO inputs, and the regression test checks that the import remains present when IntInput( is used.

Validation after the update:

python3 -m json.tool src/backend/base/langflow/agentic/flows/LangflowAssistant.json >/dev/null
uv run pytest src/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.py -q
PASS: 2 passed
uv run ruff check src/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.py
PASS
git diff --check HEAD~1..HEAD
PASS

@kiranmagic7

Copy link
Copy Markdown
Author

CI follow-up for current head 92cbb88f516ad2fb5cb37b6a2ad0f65e944f1747: the PR-specific lanes I can see are passing, including backend tests, frontend unit/e2e shards, Docker/templates, Ruff, validation, and CodeRabbit. The aggregate CI Success job is failing because the repository nightly PyPI status gate returned should-proceed: false and reports that the nightly package was not updated today: https://github.com/langflow-ai/langflow/actions/runs/27315791336/job/80699535291\n\nI don't see a branch change to make for that blocker from this PR; the local proof from the last push still applies.

@kiranmagic7

Copy link
Copy Markdown
Author

Status check on current head 92cbb88f: the PR-specific CI lanes are passing and the external nightly PyPI aggregate gate was clarified in the thread on June 11.

When a reviewer has bandwidth, the fix is narrowly scoped to guarding the component_code_search column input against unsupported non-string types — no logic changes outside that guard.

@kiranmagic7

Copy link
Copy Markdown
Author

Refreshed this branch against current main to clear the merge conflict. New head: 951b8f97e24e2a90af982615b0f36c33c9dd9267.

Conflict resolution was limited to LangflowAssistant.json's embedded component_code_search code:

  • Kept column as an internal input pinned to text, so it is not exposed as an LLM tool argument.
  • Preserved the IntInput import and number_candidates input.
  • Kept the descriptive unknown-column ValueError regression.
  • Carried forward the current-main candidate-count default of 10 where compatible.

Local proof on 951b8f97e24e2a90af982615b0f36c33c9dd9267:

node -e "JSON.parse(require('fs').readFileSync('src/backend/base/langflow/agentic/flows/LangflowAssistant.json','utf8')); console.log('json ok')"
json ok

git diff --check
PASS

uv run pytest src/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.py -q
2 passed, 1 warning

The PR may still be subject to the repo's aggregate/nightly CI gate, but the branch conflict is cleared and the focused regression is green.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jun 24, 2026
@kiranmagic7

Copy link
Copy Markdown
Author

Status check after the June 24 rebase: current head 951b8f97e2e047da3aa920aa2b742c621adc6255 is mergeable from REST and the checks are settled at 101 success, 7 skipped, 0 failures, and 0 pending.

Review focus remains the narrow component_code_search column guard for unsupported non-string values; no logic outside that guard changed in the refresh.

@kiranmagic7

Copy link
Copy Markdown
Author

Friendly follow-up after the latest live check: current head 951b8f97e2e047da3aa920aa2b742c621adc6255 is mergeable, with 101 checks passing, 7 skipped, and no failures. The PR is blocked only on required review.

Review focus: the narrow component_code_search guard that keeps column internal/pinned to text and raises a descriptive error for unsupported columns.

@kiranmagic7

Copy link
Copy Markdown
Author

Friendly follow-up after the latest live check: current head 951b8f97e2e047da3aa920aa2b742c621adc6255 is still mergeable, with 94 visible checks passing, 6 skipped, and no failures or pending checks. The PR appears blocked only on required review.

Review focus is the same narrow guard: keep the bundled component_code_search column input internal/pinned to text, and raise a descriptive error for unsupported column values rather than exposing or accepting arbitrary non-string input.

@kiranmagic7
kiranmagic7 force-pushed the kiran/component-code-search-column-guard branch from 951b8f9 to bf82246 Compare July 23, 2026 15:11
@kiranmagic7

Copy link
Copy Markdown
Author

Rebased this branch onto current main and cleared the merge conflict. New head: bf82246ed9aafaa1f2426e4cc0195324b7bb5c91.

Conflict resolution was limited to LangflowAssistant.json and kept the same narrow behavior:

  • component_code_search.column stays internal, pinned to text, and is not exposed as a model tool argument.
  • The current-main number_candidates default stays at 10.
  • The IntInput import and descriptive unknown-column failure path remain covered by the regression test.

Local proof on the refreshed head:

node -e 'JSON.parse(require("fs").readFileSync("src/backend/base/langflow/agentic/flows/LangflowAssistant.json", "utf8")); console.log("json ok")'
json ok

uv run pytest src/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.py -q
2 passed, 1 warning

uv run ruff check src/backend/tests/unit/agentic/flows/test_langflow_assistant_component_code_search.py
All checks passed!

git diff --check upstream/main...HEAD
PASS

GitHub now reports the PR mergeable again; hosted checks have restarted on the refreshed head.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Jul 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

1 participant