Seth Claude Sonnet 5 commited on
Commit ·
a12eba7
1
Parent(s): c7a1227
Surface real Drive API errors instead of silently reporting fake success
Browse fileslist_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>
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 |
-
|
| 180 |
-
|
|
|
|
| 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:
|