prestodb/presto · error · PrestoException
SHEET_BAD_DATA
SHEET_BAD_DATA
Error message
Sheet %s.%s is empty
What it means
SimpleLarkSheetsApi.getHeaderRow reads the first row of a sheet via the Lark Sheets value-range API and throws SHEET_BAD_DATA when the returned values array is empty — i.e. the sheet has no rows at all. The connector requires at least a header row to derive column names.
Source
Thrown at presto-lark-sheets/src/main/java/com/facebook/presto/lark/sheets/api/SimpleLarkSheetsApi.java:105
}
}
@Override
public List<String> getHeaderRow(String token, String sheetId, int columnCount)
{
String lastColumnLabel = LarkSheetsUtil.columnIndexToColumnLabel(columnCount - 1);
String range = format("%s!A1:%s1", sheetId, lastColumnLabel);
try {
SheetsService.SpreadsheetsValuesGetReqCall request = sheetsService.getSpreadsheetss().valuesGet();
request.setSpreadsheetToken(token);
request.setRange(range);
Response<SpreadsheetsValuesGetResult> response = request.execute();
checkResponse(response);
SpreadsheetsValuesGetResult data = response.getData();
Object[] values = data.getValueRange().getValues();
if (values.length == 0) {
throw new PrestoException(LarkSheetsErrorCode.SHEET_BAD_DATA,
format("Sheet %s.%s is empty", mask(token), sheetId));
}
if (!(values[0] instanceof List)) {
throw new PrestoException(LARK_API_ERROR,
format("Illegal response data of sheet %s @ %s", mask(token), range));
}
List<?> header = ((List<?>) values[0]);
return header.stream().map(obj -> obj == null ? null : obj.toString()).collect(Collectors.toList());
}
catch (Exception e) {
throw wrapApiError(e, format("Could not get data of sheet %s @ %s", mask(token), range));
}
}
@Override
public SheetValues getValues(String token, String range)
{
try {View on GitHub (pinned to 55bb57d202)
Solutions
- Add a header row (and at least one data row) to the sheet, then retry.
- Verify the sheetId and range in the table/metadata definition point at the intended populated region.
- Catch PrestoException with code SHEET_BAD_DATA and surface a clearer message asking the user to populate the sheet.
Example fix
// before
PrestoException e = /* SHEET_BAD_DATA: Sheet <token>.<sheetId> is empty */;
// after — validate externally before querying
if (sheetIsEmpty(spreadsheet, sheetId)) {
throw new UserGuideException("Populate sheet with a header row first");
} Defensive patterns
Strategy: validation
Validate before calling
// before querying, verify the range has data via a metadata/preview call
boolean empty = api.getValues(token, sheetId, range) == null; // or check returned rows.isEmpty()
if (empty) throw new IllegalStateException("Sheet must contain a header row before querying"); Type guard
boolean isNonEmptySheet(SheetValues v) { return v != null && v.getRows() != null && !v.getRows().isEmpty(); } Try / catch
try { header = api.getHeaderRow(token, sheetId, range); } catch (PrestoException e) { if (isErrorCode(e, LarkSheetsErrorCode.SHEET_BAD_DATA)) { promptUserToAddHeaderRow(); } else { throw e; } } Prevention
- Ensure every mapped sheet has a header row before creating tables on it.
- Double-check sheetId and range values in table metadata.
- Add a preflight readability check (isReadable) before registering the table.
When it happens
Trigger: Querying a lark-sheets table whose underlying spreadsheet range is completely empty (no header row, values array length 0 returned from getValueRange().getValues()).
Common situations: Pointing a table definition at a brand-new/blank sheet; wrong sheetId or range so the API returns an empty range; someone cleared all rows of the sheet.
Related errors
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/e641e067134e9eda.
Report an issue: GitHub.