Skip to content

entityChangesInBlock fails with "UNION types bytea and text cannot be matched" on schemas mixing Bytes and String IDs #6695

Description

@madumas

Sibling of #4433 — same endpoint, different failing query, unrelated root cause.

Symptom. On a deployment whose entity types use different ID types (some Bytes, some String/ID), entityChangesInBlock fails:

{
  entityChangesInBlock(subgraphId: "QmXooQwKjSjMePubP3qGQP9JPNhRPr2bB2KWpN9pvrfutz", blockNumber: 23982654) {
    updates { type entities }
    deletions { type entities }
  }
}
{ "errors": [ { "message": "Store error: store error: UNION types bytea and text cannot be matched" } ] }

Reproduced on: graph-node 0.42.1, and independently on 3-5 third-party indexers running 0.36.0-0.44.0 for the same deployment — the failure follows the deployment's schema, not the node.

Where it comes from. FindPossibleDeletionsQuery (store/postgres/src/relational_queries.rs) builds one statement per deployment by concatenating one branch per entity table:

select 'Transfer' as entity, 0 as causality_region, e.id from sgdN.transfer e where ...
union all
select 'Account'  as entity, 0 as causality_region, e.id from sgdN.account  e where ...

e.id is selected raw, and its column type is per-entity: text for ID/String ids, bytea for Bytes ids. UNION ALL requires a common type per column position, so any schema mixing the two is rejected by Postgres before a single row is read.

Worth noting the asymmetry with the sibling query: FindChangesQuery selects to_jsonb(e.*), which is jsonb on every branch and therefore unaffected. Only the deletions query trips on this.

Impact: same as #4433entityChangesInBlock is the cheapest indexer-side way to localise a POI divergence (diffing which entity types were written at the diverging block against another indexer). Deployments with mixed-ID schemas lose that signal entirely. Neither this nor #4433 affects indexing or query serving: the call chain (entityChangesInBlock -> SubgraphStore::entity_changes_in_block -> DeploymentStore::get_changes -> Layout::find_changes) is read-only, and find_changes has no other caller.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions