Skip to content

chore: revert GraphQL builder from 2.x to 1.x - #690

Merged
vsseixaso merged 1 commit into
masterfrom
chore/revert-graphql-builder-2-to-1
May 5, 2026
Merged

chore: revert GraphQL builder from 2.x to 1.x#690
vsseixaso merged 1 commit into
masterfrom
chore/revert-graphql-builder-2-to-1

Conversation

@vsseixaso

@vsseixaso vsseixaso commented May 5, 2026

Copy link
Copy Markdown
Contributor

What problem is this solving?

GraphQL builder 2.x introduced strict variable coercion via a newer graphql-js runtime. Third-party store apps that cannot be updated are sending variables with types that don't exactly match the schema declarations (e.g. quantity: 1 as an integer where the schema expects String, seller: 1 as integer, geoCoordinates: [float, float] where [String] is expected, and category/document id as a string where Int is expected).

These mismatches cause hard GraphQLError validation failures before resolvers are even reached. From the collected error logs, we identified the following distribution:

Pattern Percentage
quantity: 1 (Int) → expected String ~69.5%
seller: 1 (Int) → expected String ~13.6%
category id: "20" (String) → expected Int ~12.3%
geoCoordinates: [float] → expected [String] ~4.7%

Reverting to graphql@1.x restores the lenient coercion behaviour of the previous runtime. The node@7.x upgrade (Node 20, @vtex/api v7) introduced in #687 is kept — only the GraphQL builder version is reverted.

Note: The upgrade to GraphQL builder 2.x will be reintroduced in a separate PR, where the identified error scenarios will be properly handled.

How to test it?

Regression script (test-errors-regression.sh in repo root) sends the exact queries and variable shapes extracted from errors.csv and asserts HTTP 200 with no errors block.

Results against the linked workspace:

shipping: quantity=1 (Int) in variables — real query     PASS
shipping: quantity="1" (String) in variables             PASS
shipping: quantity=2 (Int)                               PASS
shipping: seller=1 (Int) in variables — real query       PASS
shipping: seller="1" (String) in variables               PASS
category: id="20" (String) in variables — real query     PASS
category: id="1000240" (String) in variables             PASS
category: id=1 (Int, control)                            PASS
shipping: geoCoordinates=[4.5578,51.9293] (Float)        PASS
shipping: geoCoordinates=[-43.17,-22.90] (Float BR)      PASS
shipping: literals inline (no variables)                 PASS
category: literal id=1 (no variables)                    PASS
brands: basic smoke                                      PASS
documents: pageSize="2" (String) in variables            PASS

RESULTS: 14 passed

Workspace

Screenshots or example usage:

Before (graphql@2.x) — error from production logs:

Variable "$items" got invalid value 1 at "items[0].quantity";
Expected type String. String cannot represent a non string value: 1

After (graphql@1.x) — same request:

HTTP 200 — data returned normally

Describe alternatives you've considered, if any.

  • Custom scalars (FlexibleInt, FlexibleString, etc.): Implementing custom scalars that accept both types was explored. However, this changes the type names visible in the SDL, which breaks any client that declares variables with the original types (e.g. $id: Int fails against an argument now typed FlexibleInt). Since third-party apps cannot be updated, this approach would trade one class of breakage for another.
  • Resolver-level casting: Casting in resolvers only runs after GraphQL validation passes. The errors happen during variable coercion, before resolvers are invoked, so this approach does not address the root cause.

Related to / Depends on

Reverts the GraphQL builder portion of #687.
Node builder upgrade (node@4.xnode@7.x) from #687 is not reverted.

Made with Cursor

Builder 2.x introduced strict variable coercion that broke ~9,300
production requests/day from third-party apps that cannot be updated.

The most common failures (from errors.csv):
- quantity: 1 (Int) where schema expected String → 6,467 errors
- seller: 1 (Int) where schema expected String → 1,264 errors
- category id: "1000240" (String) where schema expected Int → 1,147 errors
- geoCoordinates: [float, float] where schema expected [String] → 433 errors

Reverting to graphql@1.x restores the lenient coercion behaviour of the
previous runtime while keeping the node@7.x upgrade (Node 20).

The four custom directive declarations added for node@7.x SDL validation
(withSegment, withOrderFormId, withCurrentProfile, toVtexAssets) are
intentionally kept — they are a node@7.x runtime requirement, not a
graphql@2.x one.

Co-authored-by: Cursor <cursoragent@cursor.com>
@vsseixaso
vsseixaso requested a review from a team as a code owner May 5, 2026 01:56
@vsseixaso
vsseixaso requested review from RodrigoTadeuF, leo-prange-vtex and mendescamara and removed request for a team May 5, 2026 01:56
@vtex-io-ci-cd

vtex-io-ci-cd Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

Hi! I'm VTEX IO CI/CD Bot and I'll be helping you to publish your app! 🤖

Please select which version do you want to release:

  • Patch (backwards-compatible bug fixes)

  • Minor (backwards-compatible functionality)

  • Major (incompatible API changes)

And then you just need to merge your PR when you are ready! There is no need to create a release commit/tag.

  • No thanks, I would rather do it manually 😞

@vsseixaso vsseixaso self-assigned this May 5, 2026
@vsseixaso
vsseixaso requested review from vmourac-vtex and removed request for RodrigoTadeuF and leo-prange-vtex May 5, 2026 02:04
@vsseixaso

Copy link
Copy Markdown
Contributor Author

@mendescamara, o GraphQL 2.x é mais rígido com tipos e acabou afetando alguns merchants que enviam valores no formato errado.

A ideia aqui é voltar pro builder 1.x por enquanto e tratar esses casos antes de subir de novo pro 2.x em outro PR.

@vmourac-vtex vmourac-vtex left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM
Nice to have validated against all regressions!

@vsseixaso
vsseixaso merged commit f4c56c3 into master May 5, 2026
8 of 9 checks passed
@vsseixaso
vsseixaso deleted the chore/revert-graphql-builder-2-to-1 branch May 5, 2026 14:05
@vtex-io-ci-cd

vtex-io-ci-cd Bot commented May 5, 2026

Copy link
Copy Markdown
Contributor

Your PR has been merged! App is being published. 🚀
Version 2.175.0 → 2.175.1

After the publishing process has been completed (check #vtex-io-releases) and doing A/B tests with the new version, you can deploy your release by running:

vtex deploy vtex.store-graphql@2.175.1

After that your app will be updated on all accounts.

For more information on the deployment process check the docs. 📖

vsseixaso added a commit that referenced this pull request May 7, 2026
## What problem is this solving?

Builder `2.x` requires `@auth` on every query and mutation. The previous
upgrade attempt (#687) was reverted in #690 due to strict variable
coercion errors — **not** because of this requirement. That root cause
was fixed by the `@coerce` directive in #692, so the upgrade is safe to
land now.

## What changed?

- `manifest.json`: `"graphql": "1.x"` → `"graphql": "2.x"`
- `graphql/schema.graphql`: `@auth(scope: PUBLIC)` added to all queries
and mutations; `scalar Upload` declaration added

All fields use `scope: PUBLIC`, preserving the same public-by-default
behaviour as `1.x`.

## How to test it?

Run `./test-errors-regression.sh` against a linked workspace — all 14
regression cases should pass.

## Related

Re-introduces the GraphQL builder portion of #687.
Depends on the coercion fix from #692.

Made with Cursor

Made with [Cursor](https://cursor.com)

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants