Skip to content

Comments

[pull] main from expo:main#612

Merged
pull[bot] merged 17 commits intocode:mainfrom
expo:main
Feb 20, 2026
Merged

[pull] main from expo:main#612
pull[bot] merged 17 commits intocode:mainfrom
expo:main

Conversation

@pull
Copy link

@pull pull bot commented Feb 20, 2026

See Commits and Changes for more details.


Created by pull[bot] (v2.0.0-alpha.4)

Can you help keep this open source service alive? 💖 Please sponsor : )

GuillaumeOj and others added 17 commits February 20, 2026 21:30
# Why

<!--
Please describe the motivation for this PR, and link to relevant GitHub
issues, forums posts, or feature requests.
-->

In Submit's docs, current links for iOS and Android specific options are
currently pointing to specific options for `Build`.
Related issue: #43313

# How

<!--
How did you build this feature or fix this bug and why?
-->

This fix add suffix `-1` to existing links, to actually point to the
right anchors.

# Test Plan

<!--
Please describe how you tested this change and how a reviewer could
reproduce your test, especially if this PR does not include automated
tests! If possible, please also provide terminal output and/or
screenshots demonstrating your test/reproduction.
-->

Test by running dev docs locally and checking links point to the right
anchors.

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [ ] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [x] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
# Why

<!--
Please describe the motivation for this PR, and link to relevant GitHub
issues, forums posts, or feature requests.
-->

Fix ENG-19555

The docs site uses `trailingSlash: true` in `next.config.ts`, but
`next/link`'s internal `resolveHref` normalizes trailing slashes
differently during SSR vs client hydration. The server renders hrefs
without a trailing slash while the client adds one, producing a noisy
hydration mismatch warning in the dev overlay. This is dev-only with
zero production impact (the site uses `output: 'export'`, so there is no
SSR/hydration cycle in production).

Example mismatch:
```
Server: <a href="/get-started/introduction">
Client: <a href="/get-started/introduction/">
```

## How

- Add `common/suppress-trailing-slash-warning.ts`, a self-contained
side-effect module that intercepts the hydration warning through both of
the Next.js dev overlay's independent error reporting:
- (console.error):** Wraps `console.error` to filter out warnings where
the only attribute diff is a trailing slash on `href`. Joins all string
args before checking because React 19 splits the warning across multiple
arguments.
## Test Plan

- Delete `.next` directory in `docs/` app
- Run `yarn run dev` and navigate any page to confirm there is no
Trailing slash mismatch hydration issue on any page.
- Hard-refresh several times to verify consistency.
- Confirm client-side navigation and link prefetching still work
normally.

## Checkist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [ ] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
## Why

The Expo Router section on the Guides overview page
(`/guides/overview/`) has three internal links pointing to old paths
that no longer exist. These links either rely on redirects or lead to
404s.

## How

- Update the "Expo Router" link from
`/router/basics/layout/#root-layout` to `/router/introduction/`, which
is the correct landing page for the Expo Router docs.
- Update the "Hooks API" link from `/router/reference/hooks/` to
`/versions/latest/sdk/router/#hooks`, where the hooks documentation now
lives.
- Update the "Authentication" link from
`/router/reference/authentication/` to
`/router/advanced/authentication/`, matching the current file location.

## Test Plan

Visit the Guides overview page and verify all five links in the Expo
Router section navigate to the correct pages without relying on
redirects.

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [ ] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
…ersionString (#43289)

# Why

An issue has been reported in the previoust repository:
software-mansion-labs/expo-brownfield-target#42
reporting that not having `CFBundleShortVersionString` in the Plist
generated in the framework causes validation failure when uploading to
App Store Connect:

```
Validation failed
The bundle 'Payload/MyApp.app/Frameworks/MyLibName.framework' is missing plist key. 
The Info.plist file is missing the required key: CFBundleShortVersionString. 
Please find more information about CFBundleShortVersionString at https://developer.apple.com/documentation/bundleresources/information_property_list/cfbundleshortversionstring 
```

# How

Since we already pass some hardcoded version in the `Info.plist`
template and issue is still reproducible, it's related to the generated
Plist file configured via build settings in the config plugin. Updated
the build settings with two additional properties:

```ts
  INFOPLIST_KEY_CFBundleShortVersionString: `"${version}"`,
  ...
  MARKETING_VERSION: `"${version}"`,
```

Where `version` is either `config.ios.version`, `config.version` or
`1.0` if neither is present

# Test Plan

Verified compiled framework before and after the changes:

BEFORE:

```json
{
  "BuildMachineOSBuild" => "25A362"
  "CFBundleDevelopmentRegion" => "en"
  "CFBundleDisplayName" => "expoappbrownfield"
  "CFBundleExecutable" => "expoappbrownfield"
  "CFBundleIdentifier" => "host.exp.expoappbrownfield"
  "CFBundleInfoDictionaryVersion" => "6.0"
  "CFBundleName" => "expoappbrownfield"
  "CFBundlePackageType" => "FMWK"
  "CFBundleSupportedPlatforms" => [
    0 => "iPhoneOS"
  ]
  "CFBundleVersion" => "1"
  ...
}
```

AFTER:

```json
{
  "BuildMachineOSBuild" => "25A362"
  "CFBundleDevelopmentRegion" => "en"
  "CFBundleDisplayName" => "expoappbrownfield"
  "CFBundleExecutable" => "expoappbrownfield"
  "CFBundleIdentifier" => "host.exp.expoappbrownfield"
  "CFBundleInfoDictionaryVersion" => "6.0"
  "CFBundleName" => "expoappbrownfield"
  "CFBundlePackageType" => "FMWK"
  "CFBundleShortVersionString" => "1.0.0" <------------- ADDED
  "CFBundleSupportedPlatforms" => [
    0 => "iPhoneOS"
  ]
  "CFBundleVersion" => "1"
  ...
}
```

# Checklist

- [X] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [X] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
…3317)

## Summary
- Add full support for non-interactive mode in `create-expo-module` for
CI/CD environments
- Add CLI options to provide all module configuration values without
prompts
- Add E2E tests that run in CI

## Changes

### Non-interactive mode detection
- Automatically enabled when `CI=1` or `CI=true`
- Automatically enabled when stdin is not a TTY

### New CLI options
- `--name <name>` - Native module name (e.g., MyModule)
- `--description <description>` - Module description
- `--package <package>` - Android package name (e.g.,
expo.modules.mymodule)
- `--author-name <name>` - Author name for package.json
- `--author-email <email>` - Author email for package.json
- `--author-url <url>` - URL to the author's profile
- `--repo <url>` - URL of the repository

### E2E tests
- Added `e2e/` directory with Jest tests
- Tests CLI flags and module creation in CI mode
- Added GitHub Actions workflow for CI

## Test plan
- [x] `yarn test:e2e` passes locally
- [x] Tests run in ~40 seconds (4 tests)
- [x] Module creation works with `CI=1`

## Usage example
```bash
# CI mode (auto-detected)
CI=1 npx create-expo-module my-module --no-example

# With custom values
npx create-expo-module my-module \
  --no-example \
  --name MyModule \
  --description "My awesome module" \
  --package com.mycompany.mymodule \
  --author-name "John Doe"
```

🤖 Generated with [Claude Code](https://claude.ai/code)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
pod-install@1.0.14
patch-project@55.1.4
jest-expo@55.0.7
install-expo-modules@0.14.7
expo-widgets@55.0.0-alpha.8
expo-web-browser@55.0.7
expo-video@55.0.7
expo-updates@55.0.9
@expo/ui@55.0.0-preview.7
expo-task-manager@55.0.7
expo-router@55.0.0-preview.9
expo-notifications@55.0.8
expo-modules-core@55.0.10
expo-modules-autolinking@55.0.6
expo-module-template@55.0.6
expo-media-library@55.0.7
expo-maps@55.0.7
expo-location@55.1.0
expo-keep-awake@55.0.4
expo-image-picker@55.0.7
expo-image-manipulator@55.0.7
expo-image@55.0.4
expo-file-system@55.0.7
expo-doctor@1.18.7
expo-dev-menu@55.0.7
expo-dev-launcher@55.0.8
expo-contacts@55.0.7
expo-crypto@55.0.7
expo-constants@55.0.6
expo-calendar@55.0.7
expo-brownfield@55.0.9
expo-auth-session@55.0.5
expo-audio@55.0.7
expo@55.0.0-preview.12
create-expo-module@2.1.4
create-expo@3.6.5
babel-preset-expo@55.0.6
@expo/require-utils@55.0.1
@expo/prebuild-config@55.0.6
@expo/metro-config@55.0.7
@expo/local-build-cache-provider@55.0.5
@expo/fingerprint@0.16.4
@expo/config@55.0.7
@expo/cli@55.0.10
expo-asset@55.0.6
expo-linking@55.0.5
expo-sqlite@55.0.7
expo-splash-screen@55.0.7
expo-device@55.0.8
expo-system-ui@55.0.7
expo-application@55.0.7
expo-manifests@55.0.7
expo-build-properties@55.0.8
expo-gl@55.0.7
expo-template-tabs@55.1.6
expo-template-default@55.1.6
expo-template-blank-typescript@55.1.6
expo-template-bare-minimum@55.0.11
expo-template-blank@55.1.6
expo-sharing@55.0.8
expo-background-task@55.0.7
expo-background-fetch@55.0.7
expo-video-thumbnails@55.0.7
expo-insights@55.0.8
expo-dev-client@55.0.7
expo-standard-web-crypto@55.0.4
expo-video-thumbnails@55.0.7
expo-system-ui@55.0.7
expo-standard-web-crypto@55.0.4
expo-sqlite@55.0.7
expo-splash-screen@55.0.7
expo-sharing@55.0.8
expo-manifests@55.0.7
expo-linking@55.0.5
expo-insights@55.0.8
expo-gl@55.0.7
expo-doctor@1.18.7
expo-device@55.0.8
expo-dev-menu@55.0.7
expo-dev-launcher@55.0.8
expo-dev-client@55.0.7
expo-crypto@55.0.7
expo-contacts@55.0.7
expo-constants@55.0.6
expo-calendar@55.0.7
expo-build-properties@55.0.8
expo-brownfield@55.0.9
expo-background-task@55.0.7
expo-background-fetch@55.0.7
expo-auth-session@55.0.5
expo-audio@55.0.7
expo-asset@55.0.6
expo-application@55.0.7
expo@55.0.0-preview.12
create-expo-module@2.1.4
create-expo@3.6.5
babel-preset-expo@55.0.6
@expo/require-utils@55.0.1
@expo/prebuild-config@55.0.6
@expo/metro-config@55.0.7
@expo/local-build-cache-provider@55.0.5
@expo/fingerprint@0.16.4
@expo/config@55.0.7
@expo/cli@55.0.10
expo-template-tabs@55.1.6
expo-template-default@55.1.6
expo-template-blank-typescript@55.1.6
expo-template-bare-minimum@55.0.11
expo-template-blank@55.1.6
expo-modules-autolinking@55.0.7
expo-web-browser@55.0.8
expo-task-manager@55.0.8
expo-updates@55.0.10
expo-notifications@55.0.9
patch-project@55.1.5
install-expo-modules@0.14.8
expo-video@55.0.8
expo-tracking-transparency@55.0.7
expo-store-review@55.0.7
expo-speech@55.0.7
expo-sms@55.0.7
expo-sensors@55.0.7
expo-secure-store@55.0.7
expo-screen-capture@55.0.7
expo-screen-orientation@55.0.7
expo-print@55.0.7
expo-network-addons@55.0.7
expo-network@55.0.7
expo-navigation-bar@55.0.7
expo-mesh-gradient@55.0.7
expo-media-library@55.0.8
expo-maps@55.0.8
expo-mail-composer@55.0.7
expo-location@55.1.1
expo-localization@55.0.7
expo-local-authentication@55.0.7
expo-live-photo@55.0.7
expo-linear-gradient@55.0.7
expo-intent-launcher@55.0.7
expo-image-picker@55.0.8
expo-image-manipulator@55.0.8
expo-haptics@55.0.7
expo-document-picker@55.0.7
expo-clipboard@55.0.7
expo-cellular@55.0.7
expo-camera@55.0.7
expo-brightness@55.0.7
expo-blur@55.0.7
expo-blob@55.0.7
expo-battery@55.0.7
expo-apple-authentication@55.0.7
@expo/app-integrity@55.0.7
expo-age-range@0.2.9
patch-project@55.1.5
install-expo-modules@0.14.8
expo-web-browser@55.0.8
expo-video@55.0.8
expo-updates@55.0.10
expo-tracking-transparency@55.0.7
expo-task-manager@55.0.8
expo-store-review@55.0.7
expo-speech@55.0.7
expo-sms@55.0.7
expo-sensors@55.0.7
expo-secure-store@55.0.7
expo-screen-capture@55.0.7
expo-print@55.0.7
expo-screen-orientation@55.0.7
expo-notifications@55.0.9
expo-network-addons@55.0.7
expo-network@55.0.7
expo-navigation-bar@55.0.7
expo-modules-autolinking@55.0.7
expo-mesh-gradient@55.0.7
expo-maps@55.0.8
expo-mail-composer@55.0.7
expo-media-library@55.0.8
expo-location@55.1.1
expo-localization@55.0.7
expo-local-authentication@55.0.7
expo-live-photo@55.0.7
expo-linear-gradient@55.0.7
expo-intent-launcher@55.0.7
expo-image-manipulator@55.0.8
expo-image-picker@55.0.8
expo-haptics@55.0.7
expo-document-picker@55.0.7
expo-device@55.0.8
expo-dev-menu@55.0.7
expo-dev-launcher@55.0.8
expo-dev-client@55.0.7
expo-crypto@55.0.7
expo-contacts@55.0.7
expo-clipboard@55.0.7
expo-constants@55.0.6
expo-cellular@55.0.7
expo-camera@55.0.7
expo-calendar@55.0.7
expo-blur@55.0.7
expo-build-properties@55.0.8
expo-brownfield@55.0.9
expo-brightness@55.0.7
expo-blob@55.0.7
expo-battery@55.0.7
expo-background-fetch@55.0.7
expo-background-task@55.0.7
expo-audio@55.0.7
expo-auth-session@55.0.5
expo-application@55.0.7
expo-asset@55.0.6
expo-apple-authentication@55.0.7
expo-age-range@0.2.9
@expo/app-integrity@55.0.7
expo@55.0.0-preview.12
create-expo-module@2.1.4
create-expo@3.6.5
babel-preset-expo@55.0.6
@expo/require-utils@55.0.1
@expo/prebuild-config@55.0.6
@expo/metro-config@55.0.7
@expo/local-build-cache-provider@55.0.5
@expo/fingerprint@0.16.4
@expo/config@55.0.7
@expo/cli@55.0.10
expo-template-tabs@55.1.6
expo-template-default@55.1.6
expo-template-blank-typescript@55.1.6
expo-template-blank@55.1.6
expo-template-bare-minimum@55.0.11
jest-expo@55.0.8
expo-linking@55.0.6
@expo/router-server@55.0.7
expo-file-system@55.0.8
expo-splash-screen@55.0.8
expo-system-ui@55.0.8
expo-sqlite@55.0.8
expo-manifests@55.0.8
expo-gl@55.0.8
expo-sharing@55.0.9
expo-video-thumbnails@55.0.8
expo-insights@55.0.9
…CLI (#43319)

# Why

We have type issues here since the type now is compatibl with the Metro
config type, but the output doesn't exactly match. Presence of this
property is strictly `useWatchman: boolean` in some edge case scenarios,
so it fails checks in `expo-doctor`. While we can fix this up, it's
easier to revert the changes in `@expo/metro-config` for now, since the
override in the CLI is sufficient.

# How

- Revert #43251 for `@expo/metro-config` (not `@expo/cli`)

# Test Plan

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [ ] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
# Why

When no tint color is used, custom icons use original rendering mode -
they use original color scheme instead of the tinted one.

# How

Use `renderMode="template"` for both icons to apply tint color

# Test Plan


https://github.com/user-attachments/assets/d5d85e37-6273-4941-b3a7-af70c25329a7

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [ ] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
# Why

This PR updates the `@expo/styleguide-cookie-consent` dependency from
version `^0.1.12` to `^0.1.13` in the documentation package.

# How

Updated the version constraint in `package.json` and regenerated the
lock file to reflect the new dependency version.

# Test Plan

Verify that the documentation site builds and runs correctly with the
updated cookie consent component. Test that cookie consent functionality
continues to work as expected.

# Checklist

- [ ] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
# Why

We used both in `@expo/cli` and only `minimatch` in
`@expo/metro-config`. The latter use is for `sideEffect` and likely safe
to swap over (this doesn't have to be 100% accurate yet, just match
current expected behaviour). The former uses it for asset exports, and
the accuracy is sufficient. `picomatch` was already used in another
place in `@expo/cli`.

# How

- Replace `minimatch` with `picomatch` in `@expo/cli` and bump
- Replace `minimatch` with `picomatch` in `@expo/metro-config`

# Test Plan

- Existing CLI E2E tests should pass

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [x] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
# Why

We should consider replacing this with `picomatch`. Without knowing the
internals of the ignore patterns, this doesn't look like a trivial
change. So for now, I'll bump the dependency. After #43323
`@expo/fingerprint` will be our only dependency that directly depends on
`minimatch`.

# How

- Bump to `minimatch@^10.2.2`

# Test Plan

- CI tests should pass

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [x] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
# Why

Stack composition components (`Stack.Screen.Title`,
`Stack.Screen.BackButton`, `Stack.Header`, `Stack.Toolbar`,
`Stack.SearchBar`) previously used React Navigation's
`navigation.setOptions()` (via `<Screen options={...} />`) to
dynamically update screen options.

This approach caused a problem - when a component was unmount its
options were not unset

# How

1. Adds central repository of Stack options which is later merged into
final options

```mermaid
flowchart TD
    subgraph "Layer 1: Static Options (lowest priority)"
        SO["screenOptions on &lt;Stack&gt;"] --> UNB[useNavigationBuilder]
        SSO["Stack.Screen options prop"] --> UNB
        UNB --> DESC[Descriptors]
    end

    subgraph "Layer 2: Composition API (highest priority)"
        T["Stack.* components"] --> REG[Composition Registry]
        N["For example:<br/>Stack.Toolbar</br>Stack.Screen.Title"]:::note -.-> T
    end


    subgraph "RouterCompositionOptionsProvider"
        DESC --> VERIFY{Verification<br/>isPreloaded?<br/>isFocused?}
        REG --> VERIFY
        VERIFY -->|Apply| MERGE["Merge: descriptor.options + composition"]
        VERIFY -->|Skip composition| PASS[Use descriptor as-is]
        MERGE --> MD[Modified Descriptors]
        PASS --> MD
    end

    MD --> NSV[NativeStackView]
    NSV --> SCREENS[Rendered Screens]

    style REG fill:#e1f5fe
    style VERIFY fill:#fff3e0
    style MD fill:#e8f5e9
    classDef note fill:#ffffcc,stroke:#999,stroke-dasharray:5 5,font-size:12px
```


# Test Plan

1. Unit tests
3. Manual testing


https://github.com/user-attachments/assets/8b57ef3c-ed63-4771-9d97-2ea613c921f3


https://github.com/user-attachments/assets/e0044088-dc3e-4cf5-8303-a66ed8a19158


https://github.com/user-attachments/assets/8a6719d5-5e29-4256-8740-94495a3694fc

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [x] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
# Why

When `EXPO_UNSTABLE_WEB_MODAL` was set to `1`, the web modal stack
didn't recognize the `Stack.Screen` screens and ignored them.

# How

Mirror the `StackClient` implementation, by extracting the
`mapProtectedScreen` and using it in web modal

# Test Plan

1. Unit tests
2. Manual testing with `EXPO_UNSTABLE_WEB_MODAL=1 yarn start:web-modal`

**Before**


https://github.com/user-attachments/assets/9b3b76f5-4f74-4b66-8dad-e2f7d0250ef3

**After**


https://github.com/user-attachments/assets/8400a34a-aa09-42f5-8807-0b5dfbe8b32a

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [x] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
# Why

The `AbortSignal` definition on `Request` and how it's used (or not
used) with `pipeline`, and a lack of a `nodeResponse.destroyed` and
`nodeResponse.writableEnded` check might be triggering an error if the
response is closed before any part of the body was sent. I can't
reproduce this issue locally, but tightening this up seems cheap and
straightforward.

This PR also addresses a few other changes:
- Reuses helpers from `http` adapters in `express` adapter again
- Drops `convertHeaders` due to the incrementing version and it being
unused (must be removed when cherry-picking)
- Replaces `nodeResponse.setHeaders` since it's known to cause issues in
Bun (see kitten/fetch-nodeshim#34)

# How

- Drive `AbortController.abort` with `error` event from response as well
- Check `writableEnded` and `destroyed` before continuing with `respond`
logic
- Replace `setHeaders` call
- Pass `Request.signal` to `pipeline` for completeness (mirrors response
ending anyway though)

# Test Plan

- CI should pass

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [x] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
# Why

The pr-labeler workflow fails with `Argument list too long` when the
fingerprint diff is large (>2MB). The fingerprint-diff output gets
expanded inline by the GitHub Actions runner, and any approach that
passes it through shell arguments or environment variables hits Linux's
ARG_MAX limit.


Before:
https://github.com/expo/expo/actions/runs/21922360042/job/63305722298?pr=43018
After:
https://github.com/expo/expo/actions/runs/22238462171/job/64335899522?pr=43081

# How

Use the fingerprint file input that the action already supports. This
makes the action write the entire state (including the diff) directly to
a JSON file on disk, completely bypassing shell argument/env var size
limits.


# Test Plan


Verify the pr-labeler workflow passes on CI for a PR that triggers
fingerprint changes.


# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
-->

- [ ] I added a `changelog.md` entry and rebuilt the package sources
according to [this short
guide](https://github.com/expo/expo/blob/main/CONTRIBUTING.md#-before-submitting)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
@pull pull bot locked and limited conversation to collaborators Feb 20, 2026
@pull pull bot added the ⤵️ pull label Feb 20, 2026
@pull pull bot merged commit 3329d41 into code:main Feb 20, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

9 participants