apache / apache/age

`id(n)` after rebinding the same variable across a `WITH` errors with `age_id(_ag_label_vertex) does not exist`

Open
#2,513 1 comment 0 reactions 0 assignees View on GitHub
bug
Dominant language
C
Stars
4.8k
Forks
523
Avg merge
1d 2h
Merged PRs (30d)
9

Description

## 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:

```pgsql
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

```pgsql
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:

1. `n` is bound by the first `MATCH (n)`;
2. `WITH 1 AS v` drops it (the `WITH` does not project `n`);
3. 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

Contributor guide

Open the contributing guide

Research direction

Reproduce the query in the official apache/age:1.8.0 Docker container with psql on an empty graph. Trace SQL generation for a variable rebound after WITH and for id(n) in WHERE, then verify the query no longer raises the age_id(_ag_label_vertex) signature error and that the listed variants still run normally.

Written by the indexing model from the issue text.

Assessment

Tech stack
postgresql
Domain
databases
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Active
Clarity
Clearly specified
Newbie friendliness
68/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.