appsmithorg/appsmith · error · AppsmithPluginException
PE-GSH-5000
PE-GSH-5000
Error message
Missing a valid response object.
What it means
Thrown by FileListMethod.transformExecutionResponse (FileListMethod.java:58) with code PE-GSH-5000. The 'List Spreadsheets' (execute) action expects a non-null JSON response from the Drive API `files` list call to iterate `response.get("files")`. A null response aborts before the files-array check.
Source
Thrown at app/server/appsmith-plugins/googleSheetsPlugin/src/main/java/com/external/config/FileListMethod.java:58
@Override
public WebClient.RequestHeadersSpec<?> getExecutionClient(WebClient webClient, MethodConfig methodConfig) {
UriComponentsBuilder uriBuilder = getBaseUriBuilder(
this.BASE_DRIVE_API_URL,
"?orderBy=name&q=mimeType%3D'application%2Fvnd.google-apps.spreadsheet'%20and%20trashed%3Dfalse"
+ SHARED_DRIVE_PARAMS,
true);
return webClient
.method(HttpMethod.GET)
.uri(uriBuilder.build(true).toUri())
.body(BodyInserters.empty());
}
@Override
public JsonNode transformExecutionResponse(
JsonNode response, MethodConfig methodConfig, Set<String> userAuthorizedSheetIds) {
if (response == null) {
throw new AppsmithPluginException(
GSheetsPluginError.QUERY_EXECUTION_FAILED, ErrorMessages.MISSING_VALID_RESPONSE_ERROR_MSG);
}
if (response.get("files") == null) {
return this.objectMapper.createArrayNode();
}
List<Map<String, String>> filesList = StreamSupport.stream(
response.get("files").spliterator(), false)
.map(file -> getSpreadsheetData((JsonNode) file, userAuthorizedSheetIds, GoogleSheetMethodEnum.EXECUTE))
.filter(Objects::nonNull)
.collect(Collectors.toList());
return this.objectMapper.valueToTree(filesList);
}
@Override
public boolean validateTriggerMethodRequest(MethodConfig methodConfig) {
return this.validateExecutionMethodRequest(methodConfig);
}View on GitHub (pinned to 8cd9021c24)
Solutions
- Re-authorize the Google Sheets datasource if the OAuth token expired.
- Enable plugin HTTP logging to inspect the actual status and body.
- Confirm the authorized Google account owns or is shared on at least one spreadsheet.
- If patching the plugin, coerce a null body to an empty object node before invoking transformExecutionResponse.
Example fix
// before — list body arrives null
public JsonNode transformExecutionResponse(JsonNode response, ...) {
if (response == null) { throw ...; }
if (response.get("files") == null) { return objectMapper.createArrayNode(); }
...
}
// after — caller coerces empty
JsonNode node = body == null ? objectMapper.createObjectNode() : objectMapper.readTree(body);
return method.transformExecutionResponse(node, config, ids); Defensive patterns
Strategy: retry
Try / catch
async function listSpreadsheetsSafe() {
try { return await listSpreadsheets.run(); }
catch (e) {
if (e && /Missing a valid response object/.test(e.message)) {
await refreshToken();
return await listSpreadsheets.run();
}
throw e;
}
} Prevention
- Keep OAuth credentials valid; expired tokens often produce null bodies.
- Confirm the authorized account owns or is shared on at least one spreadsheet.
- Enable HTTP logging to see the real Drive files-list response.
When it happens
Trigger: The Drive files-list GET returned a body that arrived null at the transform — empty response, a nulled non-JSON error, or a Webclient filter that consumed the body. The null guard is the first statement, so it fires immediately.
Common situations: OAuth token expired (401 body nulled); the authorized account has zero spreadsheets and the API returned an unexpected empty body; rate limiting (429) error body lost; response adapter misconfiguration stripping bodies.
Related errors
AI-assisted analysis of appsmithorg/appsmith@8cd9021c24 (2026-08-12).
Data as JSON: /api/errors/df5a3a7ee66c69f9.
Report an issue: GitHub.