prestodb/presto · error · PrestoException
LARK_API_ERROR
LARK_API_ERROR
Error message
Illegal response data of sheet %s @ %s
What it means
In getHeaderRow, after the empty check, the code verifies values[0] is a List (a row of cells). If the first element is not a List the Lark API returned data in an unexpected shape, and LARK_API_ERROR is thrown. This indicates a malformed or unexpected API payload rather than user data problems.
Source
Thrown at presto-lark-sheets/src/main/java/com/facebook/presto/lark/sheets/api/SimpleLarkSheetsApi.java:109
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 {
SheetsService.SpreadsheetsValuesGetReqCall request = sheetsService.getSpreadsheetss().valuesGet();
request.setSpreadsheetToken(token);
request.setRange(range);
View on GitHub (pinned to 55bb57d202)
Solutions
- Upgrade or pin the Lark SDK client library to a version matching the connector's expectations.
- Log the raw response payload to inspect the unexpected shape.
- Catch PrestoException with LARK_API_ERROR and retry or fall back to re-fetching the range.
Example fix
// before
Object[] values = data.getValueRange().getValues();
// after (defensive)
Object[] values = data.getValueRange() != null && data.getValueRange().getValues() != null
? data.getValueRange().getValues() : new Object[0]; Defensive patterns
Strategy: retry
Validate before calling
// preflight: fetch values and check first element shape before dependent logic
Object[] values = /* from getValueRange */;
if (values.length == 0 || !(values[0] instanceof List)) throw new IllegalStateException("Unexpected Lark payload shape"); Type guard
boolean hasListHeader(Object[] values) { return values != null && values.length > 0 && values[0] instanceof List; } Try / catch
try { header = api.getHeaderRow(token, sheetId, range); } catch (PrestoException e) { if (isLarkApiError(e) && e.getMessage().startsWith("Illegal response data")) { header = retryWithBackoff(3); } else { throw e; } } Prevention
- Pin the Lark SDK version and test after upgrades.
- Log raw responses to detect shape drift early.
- Add retry with backoff around header reads.
When it happens
Trigger: The Lark values API returns a values array whose first element is not a List (e.g. scalar values, null structure, or an SDK shape change after a Lark client library upgrade).
Common situations: Lark API version/SDK update changing the response structure; proxy or mock returning non-standard JSON; corrupted cached responses.
Understand the failure class
Background: "invalid response format", "malformed payload", "missing data field": when an API returns 200 but the response shape is wrong — this error's family across 23 libraries.
Related errors
AI-assisted analysis of prestodb/presto@55bb57d202 (2026-09-04).
Data as JSON: /api/errors/b0ba0b5a80c79641.
Report an issue: GitHub.