Skip to content

Bump engine and SDK to Flutter 3.44.6, fix tvOS<26 simulator crash (1.4.1) - #39

Merged
DenisovAV merged 2 commits into
devfrom
chore/flutter-3.44.6
Jul 20, 2026
Merged

Bump engine and SDK to Flutter 3.44.6, fix tvOS<26 simulator crash (1.4.1)#39
DenisovAV merged 2 commits into
devfrom
chore/flutter-3.44.6

Conversation

@MAUstaoglu

@MAUstaoglu MAUstaoglu commented Jul 19, 2026

Copy link
Copy Markdown
Member

Repins the Flutter SDK to 3.44.6 (ee80f08b) and the tvOS engine to v1.0.1-flutter3.44.6, released as 1.4.1. Also fixes #38.

Fixes #38 — crash on first frame on tvOS simulators older than 26

The simulator engine embedded Impeller metallibs compiled for the iOS simulator:

air64-apple-ios13.0.0-simulator      ← what we shipped
air64-apple-tvos13.0.0-simulator     ← what it should be

The shader build assumed the tvOS simulator would happily load iphonesimulator libraries, since it runs on the host Mac GPU. It doesn't — Metal validates the library's target platform when a pipeline is created. On a tvOS 17.5 simulator every one of ~60 render pipelines failed with Target OS is incompatible, then the engine aborted:

[FATAL:flutter/impeller/core/raw_ptr.h(30)] Check failed: weak_ptr_.lock().

tvOS 26 tolerates the mismatch, which is why this went unnoticed and why the reporter saw it work on 26.5 but not 17.5.

Simulator metallibs are now compiled against the AppleTVSimulator SDK. Device builds were never affected — they already targeted appletvos (air64_v24-apple-tvos15.0.0).

Engine fix: fluttertv/engine#6.

Verified on a real tvOS 17.5 simulator

before after
Target OS is incompatible 60 0
FATAL 1 0

After the fix the app launches and renders with hot reload and DevTools. tvOS 26.5 re-checked for regression (0 / 0).

SDK bump

3.44.6 is a three-commit hotfix over 3.44.5 (Linux native-assets crash, Android Gradle jniLibs staging). The delta carries no engine source changes and no DEPS movement, so dart_revision is identical — no SDK-hash break. Upstream's build_system/ targets were untouched, so the four mirrored subclasses needed no re-mirroring, and all 17 tvOS patches applied unchanged.

Engine artifacts

Built against tvOS SDK 26.5 (Xcode 26.6) and origin-signed; verify_artifacts.sh passes on all six variants.

Published as v1.0.1-flutter3.44.6. This supersedes v1.0.0-flutter3.44.6 under a new tag rather than replacing its assets, because the CLI caches by the engine.version string — an in-place swap would not refresh anyone who already precached.

Verification

  • dart analyze lib/0 errors, 0 warnings (135 info lints, matching baseline)
  • 297 tests pass
  • Simulator debug build OK — 10/10 FFI symbols in Runner.debug.dylib
  • Device release/AOT build OK — 10/10 FFI symbols in Runner, no Invalid SDK hash
  • App.framework/App at minos 13.0 vs sdk 26.5 (ITMS-90208 clear)
  • Crown Breaker built and submitted to external TestFlight on these artifacts as an end-to-end check

Changelog

Folds the unreleased #37 plugin-registration fix into the 1.4.1 entry, so [Unreleased] is empty again for incoming PRs.

Repins the Flutter SDK to 3.44.6 (ee80f08b) and the tvOS engine artifacts to
v1.0.0-flutter3.44.6, and releases this as 1.4.1.

3.44.6 is a three-commit hotfix over 3.44.5 (a Linux native-assets crash fix
and an Android Gradle jniLibs staging fix). It carries no engine source
changes and no DEPS movement, so dart_revision is unchanged and there is no
SDK-hash break. The artifacts were rebuilt from the 3.44.6 tree anyway so the
engine tag and the SDK pin stay in lockstep; all 17 tvOS patches applied
unchanged. Upstream's build_system targets were untouched, so the four
mirrored subclasses (TvosKernelSnapshot, TvosCopyFlutterBundle,
TvosDartPluginRegistrantTarget, TvosAotElfRelease) needed no re-mirroring.

The rebuild used tvOS SDK 26.5 (Xcode 26.6) and is origin-signed, passing
verify_artifacts.sh on all six variants.

Verified against the new artifacts: dart analyze lib/ clean (0 errors,
0 warnings), 295 tests pass, simulator debug and device release/AOT builds
both succeed with all 10 FFI symbols exported and App.framework at
minos 13.0 (ITMS-90208 clear).

Folds the unreleased #37 plugin-registration fix into the 1.4.1 entry.
Fixes #38 — apps crashed on the first frame on tvOS simulators older than
26, with all ~60 Impeller render pipelines failing "Target OS is
incompatible" followed by a raw_ptr FATAL.

The simulator engine embedded Impeller metallibs compiled for the *iOS*
simulator (air64-apple-ios13.0.0-simulator). Metal validates a library's
target platform when creating a pipeline, so the mismatch failed every
pipeline; tvOS 26 tolerates it, which is why it only reproduced on older
runtimes. The engine now compiles simulator metallibs against the
AppleTVSimulator SDK (air64-apple-tvos13.0.0-simulator). Device builds were
never affected.

Engine fix in fluttertv/engine#6; artifacts republished under a new tag
because the CLI caches by the engine.version string, so replacing assets on
the existing tag would not refresh anyone who already precached.

Verified on a tvOS 17.5 simulator with the flutter_tvos example: 60 errors
and a FATAL before, 0 and 0 after, app launches and renders with hot reload
and DevTools. tvOS 26.5 re-checked for regression. 297 tests pass, analyze
clean.
@MAUstaoglu MAUstaoglu changed the title Bump engine and SDK to Flutter 3.44.6 (1.4.1) Bump engine and SDK to Flutter 3.44.6, fix tvOS<26 simulator crash (1.4.1) Jul 19, 2026
@DenisovAV
DenisovAV merged commit 7014a93 into dev Jul 20, 2026
2 checks passed
DenisovAV pushed a commit that referenced this pull request Jul 20, 2026
* chore(release): upgrade engine to Flutter 3.44.2 (1.3.1)

Bump flutter.version to c9a6c484 (Flutter 3.44.2) and engine.version to
v1.0.0-flutter3.44.2. Engine artifacts rebuilt against Dart d684a576.

A Flutter-version-only bump keeps simulator/debug working but breaks AOT
with 'gen_snapshot: Invalid SDK hash' (old gen_snapshot cannot load kernel
compiled by the new Dart SDK), so the engine rebuild is required for
device/release builds.

* fix(platform): make tvOS platform identity correct in AOT/release builds

Platform.operatingSystem / isIOS / isTvOS carry @pragma("vm:platform-const"),
which gen_snapshot const-folds in AOT from the build's --target-os. Stock
Flutter passes --target-os ios for TargetPlatform.ios (which tvOS rides), so
release baked in operatingSystem == "ios" and isTvOS == false for all app and
plugin code — correct in JIT/debug, dead on device in release.

Keep debug and release on the same runtime-resolution path:

- TvosKernelSnapshot.build() mirrors upstream KernelSnapshot.build() but passes
  targetOS: null, so the platform-const getters are not folded and resolve at
  runtime to "tvos" (the engine's patched kHostOperatingSystemName).
- TvosArtifacts overrides flutterPatchedSdkPath / platformKernelDill for AOT
  only to the patched flutter_patched_sdk in the host engine artifact, so the
  un-folded isIOS initializer is operatingSystem == "ios" || == "tvos" and the
  isTvOS getter exists. Debug keeps the stock SDK (runtime resolution via the
  device engine makes the compile SDK irrelevant there).

Verified on a physical Apple TV in release: operatingSystem == "tvos",
isIOS == true, isTvOS == true, defaultTargetPlatform == iOS. Plugin isolation
is unaffected — discovery is keyed on the pubspec tvos: key, not Platform.isIOS.

Adds unit tests asserting the AOT frontend_server command omits --target-os and
that the artifact override applies for AOT but falls through to stock for debug.
The example info screen now surfaces the platform-identity values.

* fix(rcu): retry the configure handshake until the native plugin is ready

At app startup the native FlutterTvRemotePlugin may not have registered its
button-channel handler yet when init() pushes the initial config. The one-shot
invocation then throws MissingPluginException and the handshake is lost — native
never sets frameworkReadyForTouches and the touchpad appears dead even though
everything compiled. Retry on a short interval until the call is acknowledged or
a newer config supersedes it. Guarded by a generation counter so a superseded or
reset push bails out, and never runs on iOS/Android (init() is isTvos-gated).

* docs(changelog): document the AOT platform-identity fix in 1.3.1

1.3.1 was never tagged, and the platform-identity fix landed on the same
branch on top of the engine bump, so the release now carries a real CLI
behaviour change. Drop the "no CLI behaviour change" note, add a Fixed
section for the AOT Platform.operatingSystem/isIOS/isTvOS correction, note
the bundled flutter_tvos 1.1.1, and move the date to the actual ship date.

* fix(platform): compile profile AOT against the non-product host SDK

Profile builds crashed at startup with `Type '_NetworkProfiling' not found in
library 'dart.io'`. The patched-SDK override pointed both profile and release
at the product host_release SDK, but the non-product profile engine looks up
entry-point classes (e.g. dart:io _NetworkProfiling) that the product SDK
doesn't retain through AOT tree-shaking. Map profile to the non-product
host_debug_unopt SDK (which also carries the platform-identity patch),
matching stock Flutter's flutter_patched_sdk (profile) vs
flutter_patched_sdk_product (release) split. Release is unchanged. Verified on
a physical Apple TV.

* docs(changelog): note on-device debug (JIT/hot reload) fix for tvOS 26

The device-debug engine now maps JIT pages RWX up front so on-device --debug +
hot reload work again on tvOS 26 (which denies the RW<->RX mprotect flip). Ships
in the v1.0.0-flutter3.44.2 engine artifacts; debug-only, AOT keeps W^X.

* test(artifacts): assert engine variant selection per build mode

Guards that debug+simulator → tvos_debug_sim_arm64, debug+device →
tvos_debug_arm64, profile → tvos_profile_arm64, release → tvos_release_arm64.
A wrong mapping here is how a run mode silently picks the wrong engine.

* rcu: report configure-handshake exhaustion + narrow retry catch (PR #24 review I1/I2)

Addresses review feedback on the configure-handshake retry:

- I1: _pushConfigWithRetry now only swallows the expected
  MissingPluginException / PlatformException. Any other error (e.g. a
  _config.toMap() serialization bug) propagates instead of being retried
  50x and dropped indistinguishably from the startup race. On budget
  exhaustion it reports via FlutterError.reportError instead of giving
  up silently, consistent with the rest of the class.

- I2: rewrote the retry test with fakeAsync + virtual-time ticks so it no
  longer leans on a real-wall-clock window a starved CI runner could blow.
  The unregistered-native state is modelled by a mock handler that throws
  MissingPluginException (a null handler would fall through to the real
  platform dispatcher, which fakeAsync can't pump). Added a test that the
  retry budget exhausting reports an error.

* fix(precache): fetch only tvOS + universal artifacts

Stock `flutter precache` with no platform flags downloads every enabled
platform's artifacts (Android, iOS-engine, web, macOS). A tvOS embedder
needs none of those. The command now drives the cache itself instead of
delegating to `super.runCommand()`: it fetches the tvOS engine set plus
the universal artifacts (fonts, patched SDK, host USB-deploy tools) and
nothing else, while still honouring the stock per-platform flags
(`--ios`, `--android`, `--all-platforms`, …) when passed explicitly.

Also render the tvOS engine zips under a "tvOS Engine" header in the same
nested tree style (`  ├─ [1/6] …`) as the bundled Flutter SDK artifact.

* fix(create): exit with usage when no output directory given

`flutter-tvos create` with no output directory crashed with
`Bad state: No element` because runCommand() read `rest.first` before
validating. Call `validateOutputDirectoryArg()` up front so it prints the
friendly usage message and exits with code 2, matching stock
`flutter create`.

* docs(changelog): note precache scope + create usage fixes

* chore: upgrade to Flutter 3.44.3 (1.3.2)

Refresh the pinned engine to Flutter 3.44.3 (e1fd963c, Dart d684a576).

- bin/internal/flutter.version -> e1fd963c (Flutter 3.44.3)
- bin/internal/engine.version  -> v1.0.0-flutter3.44.3
- pubspec version              -> 1.3.2
- Rebuilt all six engine artifact variants from the 3.44.3 source tree;
  all 17 tvOS patches apply cleanly and the artifact verification gate
  passes. Dart is unchanged, so AOT loads kernel without an SDK-hash
  mismatch.
- Picks up the Flutter 3.44.3 flutter_tools fixes shipped in the SDK.

Verified: dart analyze lib/ (0 errors), 262 tests pass, simulator-debug
build succeeds, release AOT produces a valid App.framework.

* docs: refresh READMEs for 3.44.3 and flutter_tvos 1.1.1

- Root README "Current version" table -> flutter-tvos 1.3.2,
  Flutter SDK 3.44.3 (e1fd963c), engine artifacts v1.0.0-flutter3.44.3.
- flutter_tvos package README: install snippet -> ^1.1.1 and add
  Siri Remote support to the feature list (it shows on pub.dev).

* release(flutter_tvos): 1.1.2 (docs refresh)

Docs-only release so the pub.dev page picks up the README changes
(Siri Remote in the feature list, updated install snippet). No
functional or API changes.

- packages/flutter_tvos/pubspec.yaml -> 1.1.2
- packages/flutter_tvos CHANGELOG + README (install snippet ^1.1.2)
- example pubspec.lock -> 1.1.2
- CLI CHANGELOG: note bundled plugin 1.1.2

Not published — publish to pub.dev after this merges to main.

* chore: gitignore per-user SwiftPM/Xcode state under plugin tvos/

Opening a plugin's tvos/Package.swift in Xcode generates
.swiftpm/xcode/xcuserdata/ (per-user scheme state, e.g.
xcschememanagement.plist) which is not source and must not be committed.

- Add packages/flutter_tvos/tvos/.gitignore (.swiftpm/, xcuserdata/) —
  the bundled plugin's tvos/ had no .gitignore, so this junk was unignored.
- Add the same rules to the porter's generated .gitignore
  (lib/plugin_porting/templates.dart), since the porter now emits a
  tvos/Package.swift and every ported plugin would otherwise hit this.

* refactor(precache): testable artifact selection + harden flag parsing; add tests

Addresses self-review findings on the precache scoping logic:

- Extract the non-tvOS artifact selection into a pure, @VisibleForTesting
  `selectRequiredArtifacts(...)` and cover it with unit tests
  (test/general/tvos_precache_test.dart): default = universal+informative
  only, explicit platform flags add their artifacts, --all-platforms,
  feature-gating, and the android umbrella/child flags.
- Guard `argResults.wasParsed(name)` with `argParser.options.containsKey`
  so a future Flutter DevelopmentArtifact without a matching precache flag
  cannot crash the command.
- Honor an individual `--android_gen_snapshot/_maven/_internal_build` flag
  on its own, not only via the `--android` umbrella.
- Drop the misleading `cache.isUpToDate()` fast-path: it checks every
  registered artifact (including platforms we intentionally skip), so it was
  effectively always false. `updateAll` is already idempotent per-artifact.
- Add a test for `flutter-tvos create` with no output directory exiting with
  usage (code 2) instead of crashing (test/general/tvos_create_test.dart),
  plus a test/src re-export shim for createTestCommandRunner.

* test: drop the create no-args test (transitively invokes Pub in CI)

Running TvosCreateCommand through createTestCommandRunner pulls the full
FlutterCommand pipeline, which transitively touches `Pub` — the flutter_tools
test harness rejects that with "Attempted to invoke pub during test" (passes
locally, fails in CI). The create no-output-dir fix is a single stock
`validateOutputDirectoryArg()` call and is unchanged; the substantive coverage
(precache artifact selection) is fully tested in tvos_precache_test.dart.

* docs: PR template + contributing guide for the dev-branch workflow

All PRs now target dev; main only receives release merges. The PR
template asks for a CHANGELOG [Unreleased] entry, test/analyze runs,
hardware or simulator verification, and reminds contributors that the
ObjC and Swift registrant/template variants must be updated together.

* docs(changelog): add [Unreleased] section for incoming PR entries

* Skip plugin registration with a clear message when the engine isn't running (physical tvOS debug) (#37)

* fix: skip plugin registration with a clear message when the engine is not running

On a physical Apple TV the debug engine only starts with a debugger
attached (see doc/architecture.md). Launched standalone, the engine
never comes up and the generated registrant passes a nil registrar into
the first Swift plugin, crashing with an unsymbolized SIGSEGV that blames
that plugin. Probe the registry once with a synthetic key and, when it
returns nil, log a clear message naming the cause and skip registration
instead of crashing.

* docs(changelog): note the standalone-debug-launch registration guard under [Unreleased]

---------

Co-authored-by: Mehmet Ali Ustaoğlu <ali.ustaoglu@icloud.com>

* Bump engine and SDK to Flutter 3.44.6, fix tvOS<26 simulator crash (1.4.1) (#39)

* chore: bump engine and SDK to Flutter 3.44.6

Repins the Flutter SDK to 3.44.6 (ee80f08b) and the tvOS engine artifacts to
v1.0.0-flutter3.44.6, and releases this as 1.4.1.

3.44.6 is a three-commit hotfix over 3.44.5 (a Linux native-assets crash fix
and an Android Gradle jniLibs staging fix). It carries no engine source
changes and no DEPS movement, so dart_revision is unchanged and there is no
SDK-hash break. The artifacts were rebuilt from the 3.44.6 tree anyway so the
engine tag and the SDK pin stay in lockstep; all 17 tvOS patches applied
unchanged. Upstream's build_system targets were untouched, so the four
mirrored subclasses (TvosKernelSnapshot, TvosCopyFlutterBundle,
TvosDartPluginRegistrantTarget, TvosAotElfRelease) needed no re-mirroring.

The rebuild used tvOS SDK 26.5 (Xcode 26.6) and is origin-signed, passing
verify_artifacts.sh on all six variants.

Verified against the new artifacts: dart analyze lib/ clean (0 errors,
0 warnings), 295 tests pass, simulator debug and device release/AOT builds
both succeed with all 10 FFI symbols exported and App.framework at
minos 13.0 (ITMS-90208 clear).

Folds the unreleased #37 plugin-registration fix into the 1.4.1 entry.

* fix: repin engine to v1.0.1-flutter3.44.6 (tvOS simulator metallib fix)

Fixes #38 — apps crashed on the first frame on tvOS simulators older than
26, with all ~60 Impeller render pipelines failing "Target OS is
incompatible" followed by a raw_ptr FATAL.

The simulator engine embedded Impeller metallibs compiled for the *iOS*
simulator (air64-apple-ios13.0.0-simulator). Metal validates a library's
target platform when creating a pipeline, so the mismatch failed every
pipeline; tvOS 26 tolerates it, which is why it only reproduced on older
runtimes. The engine now compiles simulator metallibs against the
AppleTVSimulator SDK (air64-apple-tvos13.0.0-simulator). Device builds were
never affected.

Engine fix in fluttertv/engine#6; artifacts republished under a new tag
because the CLI caches by the engine.version string, so replacing assets on
the existing tag would not refresh anyone who already precached.

Verified on a tvOS 17.5 simulator with the flutter_tvos example: 60 errors
and a FATAL before, 0 and 0 after, app launches and renders with hot reload
and DevTools. tvOS 26.5 re-checked for regression. 297 tests pass, analyze
clean.

---------

Co-authored-by: Jonah Walker <supposedlysam@gmail.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.

App crashes at launch on tvOS 17.5 (Impeller: "Target OS is incompatible") — works on tvOS 26.5

2 participants