Skip to content

Staging exports pin adapters to a stale rc dist-tag → shipped adapter predates published features (breaks ENS) #407

Description

@pasevin

Summary

Staging-mode exports pin every @openzeppelin/adapter-* to the npm rc dist-tag, but that tag is stale. It currently resolves to 2.0.0-rc.1 (published 2026-04-03), which predates features later shipped as stable releases — most visibly the ENS / name-resolution featureset (stable 2.1.02.3.0). Result: a staging export silently installs a pre-feature adapter and the feature appears broken at runtime, even though the export scaffolding is correct.

Symptom (observed)

A freshly exported app (built-in Ethereum Sepolia, address form), exported in staging mode, shows:

Name resolution is not supported on this network

…when an ENS name is entered — despite ENS being fully wired into the export template (#401) and the UI packages being ENS-capable.

Evidence

Exported package.json (staging signature — UI pkgs stable, adapter on rc):

"@openzeppelin/ui-components": "^3.8.1",   // stable, ENS-capable ✅
"@openzeppelin/ui-react": "^3.3.0",
"@openzeppelin/ui-renderer": "^3.4.0",
"@openzeppelin/adapter-evm": "rc"          // ← resolves to stale 2.0.0-rc.1 ❌

Installed adapter + registry state:

adapter rc tag → latest (stable)
adapter-evm 2.0.0-rc.1 (Apr 3) 2.3.0
adapter-solana / -stellar / -midnight 2.0.0-rc.1 2.2.0
  • adapter-evm@2.0.0-rc.1 dist contains zero matches for resolveName / ensUniversalResolver — the name-resolution capability simply does not exist in that build, so the runtime reports UNSUPPORTED_NETWORK.
  • The ENS feature landed in stable 2.1.02.3.0 (July 2026), all via push-to-main stable releases. The RC path (publish.yml workflow_dispatch) was never run for it, so the rc dist-tag never advanced past April.

Root cause

apps/builder/src/export/PackageManager.tsapplyVersioningStrategy, env === 'staging' branch:

// Staging: Use RC versions for testing latest features
if (managedVersion.includes('-rc')) {
  updatedDependencies[pkgName] = managedVersion;
} else {
  // Otherwise fall back to the 'rc' dist-tag ...
  updatedDependencies[pkgName] = 'rc';
}

When versions.ts holds a stable semver (e.g. 2.3.0), staging pins the dependency to the bare 'rc' dist-tag. That is only correct if the rc tag is ≥ latest stable. It isn't — and nothing guarantees it. Any feature merged to stable after the last RC publish is invisible to staging exports, with no error at export time (silent regression surface).

Note: production-mode exports are unaffected — they pin ^<managedVersion> from versions.ts (e.g. ^2.3.0), so they ship ENS correctly.

Proposed fixes (any subset)

  1. PackageManager (primary): in the staging branch, only use the rc dist-tag when it is actually newer than the managed stable; otherwise fall back to ^<managedVersion> (i.e. never ship an adapter older than the production pin). Guards against tag lag structurally.
  2. Release hygiene: advance the rc dist-tag whenever a stable adapter release goes out (or run the RC workflow_dispatch after stable), so rc never trails latest.
  3. Preflight guard: a CI/export check that fails or warns when any @openzeppelin/adapter-* rc tag is older than its latest, so this can't silently recur.

References

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions