Skip to content

fix: skip Docling processing for structured data files (csv, xlsx, xls)#12487

Open
jaehee-bae wants to merge 11 commits into
langflow-ai:mainfrom
jaehee-bae:fix/structured-data-files-skip-docling
Open

fix: skip Docling processing for structured data files (csv, xlsx, xls)#12487
jaehee-bae wants to merge 11 commits into
langflow-ai:mainfrom
jaehee-bae:fix/structured-data-files-skip-docling

Conversation

@jaehee-bae

@jaehee-bae jaehee-bae commented Apr 3, 2026

Copy link
Copy Markdown

Summary

  • Structured data files (.csv, .xls, .xlsx) were incorrectly included in the Docling-compatible extension list, causing exceptions and exposing the "Advanced Parser" option for file types that don't need it.
  • Introduced STRUCTURED_DATA_EXTENSIONS as an explicit class-level constant and a module-level _STRUCTURED_DATA_EXTENSIONS to avoid duplication across TEXT_EXTENSIONS and VALID_EXTENSIONS.
  • Replaced hardcoded string checks (endswith((".csv", ".xlsx", ...))) with constant-based lookups using Path(file_path).suffix.lower().lstrip(".").
image

"Advanced parsing can process any of the Read File component's supported file types except .csv, .xlsx, and .parquet files because it is designed for document processing, such as extracting text from PDFs. For structured data analysis, use the Parser component." - docs

Root Cause

  • .xls and .xlsx were listed in DOCLING_ONLY_EXTENSIONS
    -.csv, .xls, .xlsx were included in _is_docling_compatible() via the Docling extension set
  • Hardcoded string checks for structured data formats were scattered across multiple methods, creating inconsistency

Changes

  • Remove .xls and .xlsx from DOCLING_ONLY_EXTENSIONS
  • Remove .csv, .xls, .xlsx from the Docling-compatible extension check in _is_docling_compatible()
  • Add STRUCTURED_DATA_EXTENSIONS = ["csv", "xls", "xlsx"] as a class constant (backed by module-level _STRUCTURED_DATA_EXTENSIONS)
  • Refactor TEXT_EXTENSIONS to exclude structured data extensions via module-level constant
  • Replace all hardcoded endswith() checks with STRUCTURED_DATA_EXTENSIONS lookups
  • Add dedicated processing path for structured data files

Test plan

  • .xlsx/.xls/.csv upload no longer raises Docling exception
  • "Advanced Parser" option is hidden when structured data files are selected
  • PDF and other document types remain Docling-compatible
  • VALID_EXTENSIONS correctly reflects all three extension groups without duplication
  • Unit tests updated to match new VALID_EXTENSIONS order
  • E2E test (fileUploadComponent.spec.ts) updated to reflect new extension ordering

Summary by CodeRabbit

Release Notes

  • New Features

    • Enhanced support for XLSX and XLS files as structured data, consistent with CSV and Parquet handling.
    • Standardized output format across all structured data file types.
  • Tests

    • Added comprehensive test coverage for XLSX/XLS file processing and configuration.

@github-actions github-actions Bot added the community Pull Request from an external contributor label Apr 3, 2026
@coderabbitai

coderabbitai Bot commented Apr 3, 2026

Copy link
Copy Markdown
Contributor

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

Run ID: e0b91624-3e1c-4e62-a847-1399179fb6e6

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

The changes add support for treating XLSX/XLS files as structured data formats alongside CSV and Parquet. Updates include modifying configuration UI display for these formats, adjusting output handling, removing them from Docling-only processing, and introducing early-exit structured-data handling in the file processing pipeline.

Changes

Cohort / File(s) Summary
Structured Data Extension Support
src/lfx/src/lfx/components/files_and_knowledge/file.py
Added STRUCTURED_DATA_EXTENSIONS constant including CSV, XLSX, XLS, Parquet. Updated VALID_EXTENSIONS and removed these formats from DOCLING_ONLY_EXTENSIONS. Modified update_build_config and update_outputs to use the new constant. Added early-return branch in process_files to detect and handle structured-data files separately, bypassing Docling compatibility evaluation.
Structured Data Test Coverage
src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
Added test assertions for XLSX/XLS advanced_mode display behavior. Introduced update_outputs tests validating three-output structure for single XLSX/XLS inputs. Added TestStructuredDataExtensions class verifying extension configuration, VALID_EXTENSIONS inclusion of xls, and _is_docling_compatible returning False for spreadsheet formats but True for PDF.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

🚥 Pre-merge checks | ✅ 5 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Test File Naming And Structure ⚠️ Warning Test file follows pytest conventions but has critical coverage gaps for case-sensitivity, false-positive matching, and mixed batch upload scenarios. Add parametrized tests for uppercase extensions, edge cases for false-positive files, and mixed batch scenarios; normalize extension checking using Path().suffix.lower().lstrip() consistently.
Test Quality And Coverage ❓ Inconclusive Unable to fully assess test file content. While tests for new XLSX/XLS/structured data functionality exist (+91 lines), comprehensive verification of assertion depth, edge case coverage, and error handling requires direct file viewing. Provide complete test file content to verify all major functionality pathways are tested, assertion counts per test method, and edge cases identified in review comments are covered.
✅ Passed checks (5 passed)
Check name Status Explanation
Docstring Coverage ✅ Passed Docstring coverage is 94.12% which is sufficient. The required threshold is 80.00%.
Test Coverage For New Implementations ✅ Passed The PR adds comprehensive unit tests covering updated update_build_config and update_outputs logic for XLSX/XLS files, new STRUCTURED_DATA_EXTENSIONS constant, and Docling compatibility behavior, with proper naming conventions and real outcome assertions.
Excessive Mock Usage Warning ✅ Passed The unit tests in test_file_component.py use mocks only for isolating external dependencies (subprocess, S3, Google Drive) and environment variables, while the core file-handling logic is tested directly without mocks.
Title check ✅ Passed The title accurately summarizes the main change: skipping Docling processing for structured data files, which is the core objective of the PR.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ 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 and usage tips.

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Apr 3, 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: 2

🧹 Nitpick comments (1)
src/backend/tests/unit/components/files_and_knowledge/test_file_component.py (1)

119-147: Use the real node template in these build-config tests.

Hand-building build_config here makes the assertions insensitive to schema changes in to_frontend_node(). Please start from the component’s actual frontend node and then call update_build_config() on that payload for the XLSX/XLS cases.

Based on learnings, Test component build config updates by calling to_frontend_node() to get the node template, then calling update_build_config() to apply configuration changes.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/backend/tests/unit/components/files_and_knowledge/test_file_component.py`
around lines 119 - 147, The tests hand-construct a build_config making them
brittle; instead obtain the real frontend node template from the component and
use its build_config when calling update_build_config. In the tests
(test_advanced_mode_not_available_for_xlsx and
test_advanced_mode_not_available_for_xls) instantiate FileComponent(), call
FileComponent.to_frontend_node() to get the node template, extract the node's
build_config (the settings/template field the component exposes), then pass that
build_config into FileComponent.update_build_config([...], "path") with the
appropriate file_path values and assert the advanced_mode.show/value results;
this ensures the tests follow the actual schema produced by to_frontend_node().
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/lfx/src/lfx/components/files_and_knowledge/file.py`:
- Around line 448-449: Replace the fragile endswith-based extension check with a
normalized-suffix comparison: build a set of normalized structured extensions
from self.STRUCTURED_DATA_EXTENSIONS (lowercased, no leading dot), and for each
file_path compute Path(file_path).suffix.lower().lstrip(".") and test
membership; update the logic that sets allow_advanced and
build_config["advanced_mode"]["show"] to use this check, and apply the same
normalization fix to the similar check used around the process_files()/lines
~508-509 (where file suffixes are tested) so both places use identical
normalized-suffix matching.
- Around line 1122-1128: The current fast-path short-circuits when any
structured file exists and returns rollup_data(structured_files,
structured_data), which drops non-structured files; change this so the shortcut
only runs when every input is structured (i.e., if len(structured_files) ==
len(file_list) then build structured_data using
Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)}) and return
self.rollup_data(structured_files, structured_data)); otherwise, do NOT return
early—convert structured_files to Data entries and merge them back with
non-structured files preserving the original file_list order (use file.path or
an index map) before calling rollup_data so no files are lost (refer to
structured_files, STRUCTURED_DATA_EXTENSIONS, SERVER_FILE_PATH_FIELDNAME,
rollup_data, Data, and file_list).

---

Nitpick comments:
In
`@src/backend/tests/unit/components/files_and_knowledge/test_file_component.py`:
- Around line 119-147: The tests hand-construct a build_config making them
brittle; instead obtain the real frontend node template from the component and
use its build_config when calling update_build_config. In the tests
(test_advanced_mode_not_available_for_xlsx and
test_advanced_mode_not_available_for_xls) instantiate FileComponent(), call
FileComponent.to_frontend_node() to get the node template, extract the node's
build_config (the settings/template field the component exposes), then pass that
build_config into FileComponent.update_build_config([...], "path") with the
appropriate file_path values and assert the advanced_mode.show/value results;
this ensures the tests follow the actual schema produced by to_frontend_node().
🪄 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: ea873474-4a36-4847-a12d-17f19535893c

📥 Commits

Reviewing files that changed from the base of the PR and between 65c3139 and 85922e5.

📒 Files selected for processing (7)
  • src/backend/base/langflow/initial_setup/starter_projects/Document Q&A.json
  • src/backend/base/langflow/initial_setup/starter_projects/Portfolio Website Code Generator.json
  • src/backend/base/langflow/initial_setup/starter_projects/Text Sentiment Analysis.json
  • src/backend/base/langflow/initial_setup/starter_projects/Vector Store RAG.json
  • src/backend/tests/unit/components/files_and_knowledge/test_file_component.py
  • src/lfx/src/lfx/_assets/component_index.json
  • src/lfx/src/lfx/components/files_and_knowledge/file.py

Comment thread src/lfx/src/lfx/components/files_and_knowledge/file.py Outdated
Comment on lines +1122 to +1128
# Handle structured data files (xlsx, xls, csv, parquet) - just pass through file path
# These are parsed by pandas in load_files_structured_helper, not here
structured_files = [f for f in file_list if f.path.suffix[1:].lower() in self.STRUCTURED_DATA_EXTENSIONS]
if structured_files:
# For structured data files, just return Data with file_path - no text parsing needed
structured_data = [Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)}) for f in structured_files]
return self.rollup_data(structured_files, structured_data)

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 | 🟠 Major

Don't short-circuit mixed batches here.

Line 1125 returns as soon as any structured file is present, but rollup_data() is called with structured_files only. A mixed upload like table.csv + notes.txt will silently drop the non-structured file from the result. This fast path needs to run only when every input is structured, or the structured and non-structured subsets need to be processed separately and merged back in order.

Possible guard if this shortcut is only intended for all-structured batches
-        if structured_files:
+        if structured_files and len(structured_files) == len(file_list):
             # For structured data files, just return Data with file_path - no text parsing needed
             structured_data = [Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)}) for f in structured_files]
             return self.rollup_data(structured_files, structured_data)
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
# Handle structured data files (xlsx, xls, csv, parquet) - just pass through file path
# These are parsed by pandas in load_files_structured_helper, not here
structured_files = [f for f in file_list if f.path.suffix[1:].lower() in self.STRUCTURED_DATA_EXTENSIONS]
if structured_files:
# For structured data files, just return Data with file_path - no text parsing needed
structured_data = [Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)}) for f in structured_files]
return self.rollup_data(structured_files, structured_data)
# Handle structured data files (xlsx, xls, csv, parquet) - just pass through file path
# These are parsed by pandas in load_files_structured_helper, not here
structured_files = [f for f in file_list if f.path.suffix[1:].lower() in self.STRUCTURED_DATA_EXTENSIONS]
if structured_files and len(structured_files) == len(file_list):
# For structured data files, just return Data with file_path - no text parsing needed
structured_data = [Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)}) for f in structured_files]
return self.rollup_data(structured_files, structured_data)
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/lfx/src/lfx/components/files_and_knowledge/file.py` around lines 1122 -
1128, The current fast-path short-circuits when any structured file exists and
returns rollup_data(structured_files, structured_data), which drops
non-structured files; change this so the shortcut only runs when every input is
structured (i.e., if len(structured_files) == len(file_list) then build
structured_data using Data(data={self.SERVER_FILE_PATH_FIELDNAME: str(f.path)})
and return self.rollup_data(structured_files, structured_data)); otherwise, do
NOT return early—convert structured_files to Data entries and merge them back
with non-structured files preserving the original file_list order (use file.path
or an index map) before calling rollup_data so no files are lost (refer to
structured_files, STRUCTURED_DATA_EXTENSIONS, SERVER_FILE_PATH_FIELDNAME,
rollup_data, Data, and file_list).

@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Apr 3, 2026
@jaehee-bae jaehee-bae force-pushed the fix/structured-data-files-skip-docling branch from 2d6cbf7 to c0aab93 Compare April 6, 2026 01:38
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Apr 6, 2026
@jaehee-bae jaehee-bae force-pushed the fix/structured-data-files-skip-docling branch from 75392f6 to b106578 Compare April 6, 2026 04:20
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Apr 6, 2026
jaehee-bae and others added 11 commits April 8, 2026 09:11
…s, parquet)

Structured data files were incorrectly routed through Docling, which is
designed for document parsing (PDFs, Word docs, etc.), causing an
"Advanced Parser" exception when uploading .xlsx, .xls, .csv, or .parquet
files via the File component.

Per official docs: "Advanced parsing is not needed for .csv, .xlsx, and
.parquet files because it is designed for document processing."

Changes:
- Remove .xls and .xlsx from DOCLING_ONLY_EXTENSIONS
- Add STRUCTURED_DATA_EXTENSIONS tuple (csv, xlsx, xls, parquet)
- Exclude structured data files from _is_docling_compatible()
- Route structured data files to pandas path, bypassing Docling
- Use STRUCTURED_DATA_EXTENSIONS constant in place of hardcoded tuples
- Add tests: Docling exclusion, advanced mode hiding, and output types
  for xlsx/xls files

[autofix.ci] apply automated fixes

[autofix.ci] apply automated fixes (attempt 2/3)

fix: use Path.suffix for case-insensitive structured data extension checks

- Replace str.endswith() with Path().suffix.lower().lstrip('.') in
  update_build_config and update_outputs for consistent, case-insensitive,
  false-positive-safe extension matching (.XLSX, .XLS, .CSV now handled)
- Revert STRUCTURED_DATA_EXTENSIONS back to list for consistency
- Add parametrized tests for uppercase extensions (XLSX, XLS, CSV, PARQUET)
- Add mixed batch upload scenarios (structured + docling files)
- Add false-positive tests (e.g. myxlsx.txt must not match as structured)

test: remove TestStructuredDataExtensions class

fix: remove unnecessary structured data early return in process_files

csv/xlsx/xls/parquet are not in _is_docling_compatible(), so they
already bypass Docling without the early return. The shortcut also
broke S3 flows by skipping the get_file() download step.

fix: remove parquet from STRUCTURED_DATA_EXTENSIONS
…D_EXTENSIONS

Define _STRUCTURED_DATA_EXTENSIONS and _TEXT_EXTENSIONS at module level
to resolve Python 3 class scope limitation with list comprehensions,
and prevent csv/xls/xlsx from appearing twice in VALID_EXTENSIONS.
… order

csv moved to STRUCTURED_DATA_EXTENSIONS, so compact display now shows
json, pdf, txt as the first three types. hover list updated accordingly.
@jaehee-bae jaehee-bae force-pushed the fix/structured-data-files-skip-docling branch from 8598cb8 to 4f0e841 Compare April 8, 2026 00:20
@github-actions github-actions Bot added bug Something isn't working and removed bug Something isn't working labels Apr 8, 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 community Pull Request from an external contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant