Graphify-Labs/graphify · error · RuntimeError

gws export failed for {file_id}: {stderr}

Error message

gws export failed for {file_id}: {stderr}

What it means

Raised by _run_gws_export when the `gws drive files export` subprocess exits non-zero. graphify captures stderr (falling back to stdout), truncates it to 1200 chars to keep the message readable, and raises a RuntimeError naming the file_id so the failing Drive document is identifiable in a batch scan.

Source

Thrown at graphify/google_workspace.py:121

    # Drive resource keys are sent via X-Goog-Drive-Resource-Keys. The current
    # gws export command has no custom-header flag, so do not pass resourceKey
    # as an unsupported query parameter.
    _ = resource_key
    output = output.resolve()
    output.parent.mkdir(parents=True, exist_ok=True)
    timeout = int(os.environ.get("GRAPHIFY_GOOGLE_WORKSPACE_TIMEOUT", "120"))
    result = subprocess.run(
        [exe, "drive", "files", "export", "--params", json.dumps(params), "-o", output.name],
        capture_output=True,
        cwd=output.parent,
        text=True,
        timeout=timeout,
    )
    if result.returncode != 0:
        stderr = (result.stderr or result.stdout or "").strip()
        if len(stderr) > 1200:
            stderr = stderr[:1200] + "..."
        raise RuntimeError(f"gws export failed for {file_id}: {stderr}")


def _sidecar_path(path: Path, out_dir: Path, root: "Path | None" = None) -> Path:
    # Hash the scan-root-relative, NFC-normalized path — not the absolute path.
    # The absolute form salts the sidecar name with the checkout location, so the
    # same shortcut in two clones/worktrees emits differently-named byte-identical
    # sidecars, each ingested as a distinct source doc when graphify-out/ is
    # committed (#2059; mirrors convert_office_file). NFC guards macOS NFD drift
    # (#1226). The relative path still disambiguates same-stem files.
    import unicodedata
    if root is None:
        root = out_dir.parent.parent
    try:
        key = path.resolve().relative_to(Path(root).resolve()).as_posix()
    except (ValueError, OSError):
        key = str(path.resolve())
    name_hash = hashlib.sha256(unicodedata.normalize("NFC", key).encode()).hexdigest()[:8]
    return out_dir / f"{path.stem}_{name_hash}.md"

View on GitHub (pinned to 7fe58b0b0f)

Solutions

  1. Read the embedded stderr — it names the actual cause (auth vs permissions vs not-found)
  2. Re-authenticate: `gws auth login -s drive`
  3. For slow/oversized exports, raise the timeout: GRAPHIFY_GOOGLE_WORKSPACE_TIMEOUT=300 graphify ...
  4. If the file ID is dead or inaccessible, delete/move the shortcut or fix sharing in Drive

Example fix

# before
gws auth token expires
graphify build .   # RuntimeError: gws export failed for 1AbC...: Request had invalid credentials

# after
gws auth login -s drive
graphify build .
Defensive patterns

Strategy: retry

Validate before calling

import shutil, subprocess

def gws_ready() -> bool:
    exe = shutil.which("gws")
    if exe is None:
        return False
    return subprocess.run([exe, "auth", "status"], capture_output=True).returncode == 0

Try / catch

for attempt in range(3):
    try:
        export_google_shortcut(path, out_dir)
        break
    except RuntimeError as e:
        if "gws export failed" not in str(e):
            raise
        if attempt == 2 or "credentials" in str(e) or "403" in str(e):
            raise  # non-transient: auth/permission - do not retry
        import time; time.sleep(2 ** attempt)

Prevention

When it happens

Trigger: gws is installed and runs, but export fails: expired/missing Drive auth token, 403/404 on the file ID, resource-key-protected file, Drive quota, or the per-run timeout env (GRAPHIFY_GOOGLE_WORKSPACE_TIMEOUT, default 120s) exceeded via subprocess timeout semantics surfacing as failure output.

Common situations: Auth token expired since the last `gws auth login`; shortcut points to a deleted or permission-restricted doc; shared drive files needing extra scopes; exporting a large spreadsheet past the 120s default timeout.

Related errors


AI-assisted analysis of Graphify-Labs/graphify@7fe58b0b0f (2026-08-14). Data as JSON: /api/errors/5040dc08785b8ea3. Report an issue: GitHub.