Bug description
Rebinding the same variable name in a new MATCH after a WITH clause that drops that variable, and then referencing id(n) in a WHERE clause, makes AGE 1.8.0 generate SQL that passes the raw _ag_label_vertex composite row — instead of an agtype — to the age_id() function, whose only overload is age_id(agtype). The query fails with ERROR: 42883: function ag_catalog.age_id(graph_test._ag_label_vertex) does not exist instead of executing normally.
The error is raised at SQL-generation/parse time, so it fires even on an empty graph, and no data setup is required.
Access method
- Command line via
psql, inside the official Docker container apache/age:1.8.0
Data setup
No data is required — the error reproduces on an empty graph. Only the graph itself must exist:
CREATE EXTENSION IF NOT EXISTS age;
LOAD 'age';
SET search_path = ag_catalog, "$user", public;
SELECT create_graph('graph_test');
Configuration
- None beyond the stock AGE extension. No additional modules (no PostGIS, etc.), default
search_path handling as shown above.
Command that triggers the error
SELECT * FROM cypher('graph_test', $$ MATCH (n) WITH 1 AS v MATCH (n) WHERE id(n) = v RETURN 1 $$) AS (c0 agtype);
ERROR: function ag_catalog.age_id(graph_test._ag_label_vertex) does not exist
LINE 1: ...test', $$ MATCH (n) WITH 1 AS v MATCH (n) WHERE id(n) = v RE...
^
HINT: No function matches the given name and argument types. You might need to add explicit type casts.
The trigger needs three ingredients, all present above:
n is bound by the first MATCH (n);
WITH 1 AS v drops it (the WITH does not project n);
- a second
MATCH (n) rebinds the same name to an untyped vertex, and the following WHERE id(n) = v translates id(n) to age_id(n) where n is the whole _ag_label_vertex row — no matching overload exists.
Changing any one ingredient removes the error. All of the following variants run normally (return 0 rows or a row):
- Different variable names:
MATCH (x) WITH 1 AS v MATCH (y) WHERE id(y) = v RETURN 1
- No
WITH between the two MATCH clauses: MATCH (n) MATCH (n) WHERE id(n) = 1 RETURN 1
WITH passes n through instead of dropping it: MATCH (n) WITH n MATCH (n) WHERE id(n) = 1 RETURN 1
id(n) used in RETURN instead of WHERE: MATCH (n) WITH 1 AS v MATCH (n) RETURN id(n)
- No rebinding at all:
MATCH (n) WHERE id(n) = 1 RETURN 1
Expected behavior
Rebinding a variable in a new scope after a WITH is standard Cypher. The query is legal and should either execute normally (returning the rows matching id(n) = v) or raise a normal error — it must not fail with a function-signature error about the internal _ag_label_vertex row type.
Environment
- Version: 1.8.0 (official
apache/age:1.8.0 Docker image)
- PostgreSQL: 18.1 (Debian 18.1-1.pgdg13+2), x86_64
Bug description
Rebinding the same variable name in a new
MATCHafter aWITHclause that drops that variable, and then referencingid(n)in aWHEREclause, makes AGE 1.8.0 generate SQL that passes the raw_ag_label_vertexcomposite row — instead of anagtype— to theage_id()function, whose only overload isage_id(agtype). The query fails withERROR: 42883: function ag_catalog.age_id(graph_test._ag_label_vertex) does not existinstead of executing normally.The error is raised at SQL-generation/parse time, so it fires even on an empty graph, and no data setup is required.
Access method
psql, inside the official Docker containerapache/age:1.8.0Data setup
No data is required — the error reproduces on an empty graph. Only the graph itself must exist:
Configuration
search_pathhandling as shown above.Command that triggers the error
The trigger needs three ingredients, all present above:
nis bound by the firstMATCH (n);WITH 1 AS vdrops it (theWITHdoes not projectn);MATCH (n)rebinds the same name to an untyped vertex, and the followingWHERE id(n) = vtranslatesid(n)toage_id(n)wherenis the whole_ag_label_vertexrow — no matching overload exists.Changing any one ingredient removes the error. All of the following variants run normally (return 0 rows or a row):
MATCH (x) WITH 1 AS v MATCH (y) WHERE id(y) = v RETURN 1WITHbetween the twoMATCHclauses:MATCH (n) MATCH (n) WHERE id(n) = 1 RETURN 1WITHpassesnthrough instead of dropping it:MATCH (n) WITH n MATCH (n) WHERE id(n) = 1 RETURN 1id(n)used inRETURNinstead ofWHERE:MATCH (n) WITH 1 AS v MATCH (n) RETURN id(n)MATCH (n) WHERE id(n) = 1 RETURN 1Expected behavior
Rebinding a variable in a new scope after a
WITHis standard Cypher. The query is legal and should either execute normally (returning the rows matchingid(n) = v) or raise a normal error — it must not fail with a function-signature error about the internal_ag_label_vertexrow type.Environment
apache/age:1.8.0Docker image)