{"record":{"id":"0e9c85b66465cfad","repo":"Graphify-Labs/graphify","slug":"could-not-read-google-workspace-shortcut-path","errorCode":null,"errorMessage":"could not read Google Workspace shortcut {path}: {exc}","messagePattern":"could not read Google Workspace shortcut (.+?): (.+?)","errorType":"exception","errorClass":"RuntimeError","httpStatus":null,"severity":"error","filePath":"graphify/google_workspace.py","lineNumber":68,"sourceCode":"    for key in (\"resource_key\", \"resourceKey\"):\n        value = data.get(key)\n        if value:\n            return str(value)\n    if not url:\n        return None\n    parsed = urllib.parse.urlparse(url)\n    query = urllib.parse.parse_qs(parsed.query)\n    if query.get(\"resourcekey\"):\n        return query[\"resourcekey\"][0]\n    return None\n\n\ndef read_google_shortcut(path: Path) -> dict[str, str | None]:\n    \"\"\"Read a .gdoc/.gsheet/.gslides shortcut and return export metadata.\"\"\"\n    try:\n        data = json.loads(path.read_text(encoding=\"utf-8\"))\n    except Exception as exc:\n        raise RuntimeError(f\"could not read Google Workspace shortcut {path}: {exc}\") from exc\n\n    url = str(data.get(\"url\") or \"\")\n    file_id = (\n        data.get(\"doc_id\")\n        or data.get(\"file_id\")\n        or data.get(\"fileId\")\n        or data.get(\"id\")\n        or _extract_file_id_from_url(url)\n    )\n    if not file_id:\n        resource_id = str(data.get(\"resource_id\") or \"\")\n        if \":\" in resource_id:\n            file_id = resource_id.split(\":\", 1)[1]\n\n    if not file_id:\n        raise RuntimeError(f\"Google Workspace shortcut {path} does not include a Drive file ID\")\n\n    return {","sourceCodeStart":50,"sourceCodeEnd":86,"githubUrl":"https://github.com/Graphify-Labs/graphify/blob/7fe58b0b0f3873be9a21c30106b8b8527c353aa6/graphify/google_workspace.py#L50-L86","documentation":"Raised by read_google_shortcut when a .gdoc/.gsheet/.gslides shortcut file cannot be parsed. Google Drive 'shortcut' files are tiny JSON descriptors; graphify reads them to recover the Drive file ID for export. Any failure reading the bytes or decoding them as JSON (missing file handled elsewhere, but malformed JSON, wrong encoding, or an I/O error) is wrapped in a RuntimeError naming the offending path and the underlying exception.","triggerScenarios":"Ingesting a directory containing Google Workspace shortcuts where path.read_text() or json.loads() throws — truncated file, BOM/encoding damage, a .gdoc that is actually an HTML error page saved by the Drive web UI, or a permissions error reading the file.","commonSituations":"Downloading Drive files with a tool that renames or rewrites shortcut payloads; symlinking shortcuts from another machine; files synced through channels that corrupt binary-ish content; macOS NFD path surprises are handled separately, so genuine content corruption is the usual cause.","solutions":["Inspect the file: `cat file.gdoc` — it should be a small JSON object with url/doc_id/file_id keys","Re-download or re-create the shortcut from Drive so the JSON payload is intact","If the file is not actually a Drive shortcut (wrong extension), exclude or move it so the scanner skips it"],"exampleFix":"# before\n{\"url\": \"https://docs.google.com/...\"   # truncated JSON\ngraphify build .   # RuntimeError: could not read Google Workspace shortcut\n\n# after — valid shortcut file\n{\"url\": \"https://docs.google.com/document/d/<fileId>/edit\", \"doc_id\": \"<fileId>\"}","handlingStrategy":"try-catch","validationCode":"import json\nfrom pathlib import Path\n\ndef is_readable_shortcut(path: Path) -> bool:\n    try:\n        json.loads(path.read_text(encoding=\"utf-8\"))\n        return True\n    except (OSError, json.JSONDecodeError):\n        return False","typeGuard":null,"tryCatchPattern":"try:\n    meta = read_google_shortcut(path)\nexcept RuntimeError as e:\n    if \"could not read Google Workspace shortcut\" in str(e):\n        log.warning(\"skipping corrupt shortcut %s\", path)\n    else:\n        raise","preventionTips":["Validate shortcut files parse as JSON before pointing graphify at the tree","Keep .gdoc/.gsheet/.gslides files as produced by Drive sync tools - don't hand-edit or re-save them","Log and skip bad shortcuts in batch scans instead of letting one file abort the run"],"tags":["google-workspace","json","file-corruption","ingest"],"backgroundTag":null,"analyzedSha":"7fe58b0b0f3873be9a21c30106b8b8527c353aa6","analyzedAt":"2026-08-14T19:23:21.323Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}