GFQL remote: Let/DAG queries ship an empty gfql_operations array — an unsupporting server silently returns the whole graph

Aperta
#1,955 1 commento 0 reazioni 0 assegnatari Vedi su GitHub

I maintainer di solito rispondono entro 1 giorno

Nessuno ha ancora preso questa issue.

Valutazione

Difficoltà
4/5
Tempo stimato
3-5 giorni
Idoneità per principianti
48/100
Tipo di issue
Bug
Chiarezza
Specificata chiaramente
Stato di attività
Tranquilla
Stack tecnologico
python
Ambito
api

Direzione di ricerca

Start in graphistry/compute/chain_remote.py around lines 216–231 and trace how gfql_remote() builds and validates requests for Let/DAG queries and empty dictionaries. Run the client-side reproduction in the issue and inspect the request body; add or update tests for unsupported servers and invalid empty queries. Done means unsupported DAG requests fail loudly rather than silently returning the original graph, and invalid queries raise a typed validation error.

Scritto dal modello di indicizzazione a partire dal testo della issue.

Descrizione

bug gfql

Category: silent-wrong (category 1), by construction. Repro-backed for the client half (wire body verified); the server half is INDICATIVE (no live server available to the probe).

Summary

When gfql_remote() sends a Let/DAG query it puts an empty gfql_operations array next to the real gfql_query payload, and documents in a UserWarning that an older server will therefore "return the original graph unchanged":

graphistry/compute/chain_remote.py:216-231

if is_let:
    warnings.warn(
        "gfql_remote() is sending a Let/DAG query. Servers that do not support "
        "the gfql_query field will receive an empty gfql_operations array and "
        "return the original graph unchanged. ...", UserWarning, stacklevel=2)
    request_body = {"gfql_operations": [], "gfql_query": chain_json, "format": format}

An empty operation list is a valid GFQL program whose result is the identity. So on an unsupporting server the failure mode is a plausible, wrong answer (the whole graph) rather than an error, and the client has no way to tell the two apart: there is no capability negotiation, no server-version check, and no post-hoc assertion on the response. The only signal is a UserWarning, which is invisible in notebooks with warnings filtered, in library code, and in any log-scraping pipeline.

A related passthrough: an empty dict is accepted with no validation at all and produces the same identity request.

Repro (client side, no server)

from unittest.mock import MagicMock, patch
import pandas as pd, graphistry, json
from graphistry.compute.ast import n, ASTLet
from graphistry.compute.chain import Chain

g = graphistry.edges(pd.DataFrame({'s':[0],'d':[1]}),'s','d').nodes(pd.DataFrame({'id':[0,1]}),'id')
g.session.api_token='tok'; g.session.certificate_validation=True
OK = MagicMock(ok=True, json=lambda: {"nodes": [], "edges": []}, headers={"content-type":"application/json"})

for q in [ASTLet({'a': Chain([n({'x':'a'})])}), {}]:
    with patch("graphistry.compute.chain_remote.requests.post") as p, \
         patch.object(type(g),'base_url_server', lambda self:'https://t'):
        p.return_value = OK
        g.gfql_remote(q, api_token='tok', dataset_id='ds-1', format='json')
        print(json.dumps(p.call_args.kwargs['json'])[:160])
{"gfql_operations": [], "gfql_query": {"type": "Let", "bindings": {...}}, "format": "json", "engine": "pandas"}
{"gfql_operations": [], "gfql_query": {}, "format": "json", "engine": "pandas"}      # chain={} — no validation error

Expected

  • Do not use "valid program with identity semantics" as the back-compat placeholder. Either omit gfql_operations entirely for Let queries, or send a sentinel that an old server must reject (so the failure is loud), or gate on an explicit server capability/version probe and raise a typed GFQLValidationError/NotImplementedError when the server cannot serve DAGs.
  • chain={} (and any dict with no recognizable type) should be a typed validation error, not an identity request.

Notes

  • Found by the 2026-08 remote/over-the-wire amplification probe. Cross-ref #1916 (local vs remote divergence).
  • Severity rationale: the campaign bar treats "returns a plausible wrong answer with no error" as the top category; a warning does not downgrade it.
Lingua principale
Python
Stelle
2.6k
Fork
229
Merge medio
1g 2h
PR unite (30g)
67

Preparare l'ambiente

Come iniziare

  1. Leggi tutta la issue e poi la guida ai contributi del progetto.
  2. Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
  3. Fai un fork del repository e lavora su un branch.
  4. Apri una pull request che faccia riferimento al numero della issue.

Altre issue di graphistry/pygraphistry

Tutte le issue di graphistry/pygraphistry

Issue simili

Altre issue su Python

Ricevi le nuove issue nella tua casella

Un breve riepilogo di issue GitHub adatte ai principianti.