Seth Claude Sonnet 5 commited on
Commit
a12eba7
·
1 Parent(s): c7a1227

Surface real Drive API errors instead of silently reporting fake success

Browse files

list_folder_files_recursive logged a warning and returned an empty list on
any files.list failure (e.g. Drive API not enabled, revoked access), which
made reindex_drive report "success, 0 files" — indistinguishable from an
actually-empty folder. It now raises with Google's own error message (often
directly actionable, e.g. a link to enable the API), which reindex_drive's
existing error handling surfaces as an "error" status with that message in
the Chat Agent status log.

Found via a real 403 on ezofis.com's Space (Drive API not yet enabled on
the Google Cloud project); verified by reproducing that exact response.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>

Files changed (1) hide show
  1. backend/app/chat_agent_drive.py +18 -3
backend/app/chat_agent_drive.py CHANGED
@@ -154,8 +154,22 @@ def refresh_access_token(refresh_token: str) -> str:
154
  return token
155
 
156
 
 
 
 
 
 
 
 
 
 
 
 
 
157
  def list_folder_files_recursive(access_token: str, folder_id: str) -> List[Dict[str, Any]]:
158
- """BFS through a Drive folder (and subfolders), returning flat list of non-folder file metadata."""
 
 
159
  headers = {"Authorization": f"Bearer {access_token}"}
160
  out: List[Dict[str, Any]] = []
161
  queue = [folder_id]
@@ -176,8 +190,9 @@ def list_folder_files_recursive(access_token: str, folder_id: str) -> List[Dict[
176
  params["pageToken"] = page_token
177
  r = requests.get(f"{DRIVE_API_BASE}/files", headers=headers, params=params, timeout=30)
178
  if r.status_code != 200:
179
- logger.warning("Drive files.list failed: %s", r.text[:300])
180
- break
 
181
  data = r.json()
182
  for f in data.get("files", []):
183
  if f.get("mimeType") == GOOGLE_FOLDER_MIME:
 
154
  return token
155
 
156
 
157
+ def _drive_api_error_message(resp: requests.Response) -> str:
158
+ """Google's error body is usually {"error": {"message": "..."}} — surface that verbatim
159
+ (it's often directly actionable, e.g. a link to enable the API) rather than raw JSON."""
160
+ try:
161
+ msg = resp.json().get("error", {}).get("message")
162
+ if msg:
163
+ return str(msg)
164
+ except Exception:
165
+ pass
166
+ return resp.text[:300]
167
+
168
+
169
  def list_folder_files_recursive(access_token: str, folder_id: str) -> List[Dict[str, Any]]:
170
+ """BFS through a Drive folder (and subfolders), returning flat list of non-folder file metadata.
171
+ Raises RuntimeError with Google's own message on any listing failure (e.g. Drive API disabled,
172
+ revoked access) — a caller silently treating that as "0 files" would misreport it as success."""
173
  headers = {"Authorization": f"Bearer {access_token}"}
174
  out: List[Dict[str, Any]] = []
175
  queue = [folder_id]
 
190
  params["pageToken"] = page_token
191
  r = requests.get(f"{DRIVE_API_BASE}/files", headers=headers, params=params, timeout=30)
192
  if r.status_code != 200:
193
+ msg = _drive_api_error_message(r)
194
+ logger.warning("Drive files.list failed (%s): %s", r.status_code, msg)
195
+ raise RuntimeError(f"Drive API error ({r.status_code}): {msg}")
196
  data = r.json()
197
  for f in data.get("files", []):
198
  if f.get("mimeType") == GOOGLE_FOLDER_MIME: