#14638·AutoGPT

ReadSpreadsheetBlock: 'N/A' and six other literal values are silently emptied, and three more Excel defects

Author: L4XBCreated Sep 16, 2026Updated Sep 16, 2026

⚠️ Search for existing issues first ⚠️

  • I have searched the existing issues, and there is no existing issue for my problem

Which Operating System are you using?

macOS

Which version of AutoGPT are you using?

Master (branch)

Which area covers your issue best?

Blocks — ReadSpreadsheetBlock (autogpt_platform/backend/backend/blocks/spreadsheet.py)

What commit or version are you using?

98381ab on master, pandas as resolved by autogpt_platform/backend/poetry.lock

Describe your issue

Three separate defects in ReadSpreadsheetBlock. The first one loses data silently and is the one I would fix first.


1. Seven ordinary cell values are emptied when reading an Excel file

pd.read_excel(file_path) applies pandas' default missing-value list, which treats a literal string N/A, NA, n/a, NULL, None, NaN or nan as a missing value. The block then writes the NaN out through to_csv, so the cell arrives at the agent as an empty string.

Workbook (column Status is text throughout):

Code | Status
A1   | N/A
A2   | NULL
A3   | NaN
A4   | None
A5   | nan
A6   | n/a
A7   | NA
A8   | ok

What the block produces today:

Code,Status
A1,
A2,
A3,
A4,
A5,
A6,
A7,
A8,ok

Seven of the eight rows lost their status. N/A is the standard way a person writes "not applicable" in a spreadsheet, and NULL is what a database export writes — so this is not an unusual cell value, and nothing anywhere signals that a value was dropped.

2. A whole number becomes a decimal when its column has one gap

A missing value upcasts the column to float, so 12 is written as 12.0:

Product | Units | Note
Cable   | 12    | spare
Hub     |       | n/a
{'Product': 'Cable', 'Units': '12.0', 'Note': 'spare'}
{'Product': 'Hub',   'Units': '',     'Note': ''}

An agent comparing Units against "12", or writing it back somewhere, gets "12.0".

Both of these are the same one-line fix:

df = pd.read_excel(file_path, dtype=object, keep_default_na=False)

Measured on the same workbook:

Code,Status          Product,Units,Note
A1,N/A               Cable,12,spare
A2,NULL              Hub,,
…                    
A8,ok

A genuinely empty cell still comes through empty, which is what it should do.

3. Only the first sheet of a workbook is read

pd.read_excel(file_path) with no sheet_name returns the first sheet. A two-sheet workbook (Q1, Q2) yields only Q1's rows; Q2 is dropped with no error and no warning. The block's description — "Reads CSV and Excel files and outputs the data as a list of dictionaries" — says nothing about sheets, so from the outside the data is simply not there.

This one needs a decision rather than a one-liner: a sheet_name input (default: the first, so nothing changes for existing agents), or reading all sheets and emitting the sheet name alongside each row. Happy to build whichever you prefer.

4. skip_columns can never skip anything

skip_columns: list[str] = SchemaField(
    description="The columns to skip from the start of the row", ...
)
...
for i, value in enumerate(row):
    if i not in input_data.skip_columns:

i is an int from enumerate and skip_columns holds str, so the membership test is always false: 0 in ["0"] is False. Whatever the user puts in that field, no column is ever skipped.

The comparison against the positional index says the intent was positional, so if str(i) not in input_data.skip_columns makes the field work as written without changing the schema. If the intent was actually column names — which the type and the wording both suggest — then it should compare against header[i]. I did not want to pick between those two for you.

One more, smaller: the Excel branch ignores the configured delimiter

delimiter is an input with a , default, but the Excel branch always writes commas via to_csv and the result is then parsed with input_data.delimiter. An agent configured with delimiter=";" — a reasonable setting for European CSVs — reads its CSV files correctly and gets a single column out of every Excel file. Passing sep=input_data.delimiter to to_csv would keep the two branches consistent.

Upload Activity Log content

Not applicable — reproduced against the source with pandas directly, not from a running instance. Each snippet above is real output, not a description.

Additional context

I have the fix for #1 and #2 ready (the one-line read_excel change) and can send a PR for it. I stopped short of opening one because the backend needs a generated Prisma client to import a block, so I could not run your own test harness here and did not want to submit a change I had only verified at the pandas level. If you would rather have the PR anyway, say so and I will open it.

Source: Significant-Gravitas/AutoGPT