Skip to content

Asset transformers overwrite the asset for pixel-density variants and fail #151813

@Albert221

Description

@Albert221
Target web_release_bundle failed: Error: User-defined transformation of asset "/Users/albert/Projects/Playground/asset_transformers_bug/assets/image.jpg" failed.
Asset transformer transformer did not produce an output file.
Input file provided to transformer: "/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Eh410U/image.jpg-transformOutput0.jpg"
Expected output file at: "/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Eh410U/image.jpg-transformOutput1.jpg"
Full command: /Users/albert/fvm/versions/3.22.2/bin/cache/dart-sdk/bin/dart run transformer --input=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Eh410U/image.jpg-transformOutput0.jpg
  --output=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Eh410U/image.jpg-transformOutput1.jpg

Steps to reproduce

  1. Prepare the project like in the Code sample section.
  2. Clean the project so there's no asset transformer cache flutter clean.
  3. Run `flutter build web --verbose.

Whether it fails or not depends on how fast the asset transformer finishes its work. I put a delay with Random() between 1 and 0 seconds delay, so if the build succeeded, please retry flutter clean and flutter build web --verbose until it fails.

Expected results

The build succeeds.

Actual results

Asset transformer fails as seen in the Logs section.

Asset transformers operate on the assets in some temporary directory, but in case of pixel-density variants (the image.jpg, 2.0x/image.jpg, etc.) the assets are moved to the same path, ignoring the 2.0x/ directories in their paths. As a result, for such three assets, the asset transformer works on only one path and very often fails because of that (or it may also lead to unwanted results). Below is the key fragment of logs:

[   +2 ms] Transforming asset using command '/Users/albert/fvm/versions/3.24.0-0.0.pre/bin/cache/dart-sdk/bin/dart run transformer --input=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput0.jpg
--output=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput1.jpg'
[        ] Transforming asset using command '/Users/albert/fvm/versions/3.24.0-0.0.pre/bin/cache/dart-sdk/bin/dart run transformer --input=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput0.jpg
--output=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput1.jpg'

Here's what I think is happening:

  1. Flutter CLI runs asset transformer for assets/image.jpg (input path X, output path Y)
  2. Flutter CLI runs asset transformer for assets/2.0x/image.jpg (input path X, output path Y - same as the previous one!)
  3. Transforming of assets/image.jpg is done.
  4. Transforming of assets/2.0x/image.jpg is done.
  5. Flutter CLI copies the output of assets/image.jpg transformation from file in path Y and cleans it afterward (file in path Y is removed)
  6. Flutter CLI copies the output of assets/2.0x/image.jpg transformation from file in path Y... it does not exist!

Code sample

Code sample
  1. Create a project with flutter create --platforms web asset_transformers_bug
  2. Enter that dir cd asset_transformers_bug
  3. Create new project for the asset transformer itself dart create -tcli transformer
  4. Paste the following code in the following files
# asset_transformers_bug/pubspec.yaml

name: asset_transformers_bug

environment:
  sdk: ">=3.4.3 <4.0.0"

dependencies:
  flutter:
    sdk: flutter
  transformer:
    path: transformer

flutter:
  uses-material-design: true
  assets:
    - path: assets/image.jpg
      transformers:
        - package: transformer
// asset_transformers_bug/lib/main.dart

import 'package:flutter/material.dart';

void main() {
  runApp(
    MaterialApp(
      home: Scaffold(
        body: Center(
          child: Image.asset('assets/image.jpg'),
        ),
      ),
    ),
  );
}
// asset_transformers_bug/transformer/bin/transformer.dart

import 'dart:io';
import 'dart:math';

import 'package:args/args.dart';

ArgParser buildParser() {
  return ArgParser()
    ..addOption('input')
    ..addOption('output');
}

void main(List<String> arguments) async {
  final argParser = buildParser();
  try {
    final results = argParser.parse(arguments);

    final input = results.option('input')!;
    final output = results.option('output')!;

    await Process.run('cp', [input, output]);

    final delay = Random().nextInt(2) == 1 ? 1 : 0;
    await Future.delayed(Duration(seconds: delay));
  } on FormatException catch (e) {
    // Print usage information if an invalid argument was provided.
    print(e.message);
    print('');
  }
}

Put any image (for example this) into asset_transformers_bug/assets/image.jpg and asset_transformers_bug/assets/2.0x/image.jpg.

Screenshots or Video

No response

Logs

I've created this code example on Flutter 3.24.0-0.0.pre because I wanted to have the asset transformers traces #146374, but I first found it out on Flutter 3.22.2.

Logs
(...)
[+6877 ms] Compiled 42,555,800 input bytes (8,573,281 characters source) to 1,277,550 characters JavaScript in 6.73 seconds using 594.438 MB of memory
[  +18 ms] dart2js: Complete
[ +243 ms] web_release_bundle: Starting due to {}
[  +60 ms] shaderc command: [/Users/albert/fvm/versions/3.24.0-0.0.pre/bin/cache/artifacts/engine/darwin-x64/impellerc, --sksl, --iplr, --json, --sl=build/web/assets/shaders/ink_sparkle.frag, --spirv=build/web/assets/shaders/ink_sparkle.frag.spirv,
--input=/Users/albert/fvm/versions/3.24.0-0.0.pre/packages/flutter/lib/src/material/shaders/ink_sparkle.frag, --input-type=frag, --include=/Users/albert/fvm/versions/3.24.0-0.0.pre/packages/flutter/lib/src/material/shaders,
--include=/Users/albert/fvm/versions/3.24.0-0.0.pre/bin/cache/artifacts/engine/darwin-x64/shader_lib]
[   +2 ms] Transforming asset using command '/Users/albert/fvm/versions/3.24.0-0.0.pre/bin/cache/dart-sdk/bin/dart run transformer --input=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput0.jpg
--output=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput1.jpg'
[        ] Transforming asset using command '/Users/albert/fvm/versions/3.24.0-0.0.pre/bin/cache/dart-sdk/bin/dart run transformer --input=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput0.jpg
--output=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput1.jpg'
[  +15 ms] Running command: /Users/albert/fvm/versions/3.24.0-0.0.pre/bin/cache/dart-sdk/bin/dart --disable-dart-dev /Users/albert/fvm/versions/3.24.0-0.0.pre/bin/cache/artifacts/engine/darwin-x64/const_finder.dart.snapshot --kernel-file
/Users/albert/Projects/Playground/asset_transformers_bug/.dart_tool/flutter_build/676642b58d55dac85560580d77372536/app.dill --class-library-uri package:flutter/src/widgets/icon_data.dart --class-name IconData --annotation-class-name _StaticIconProvider
--annotation-class-library-uri package:flutter/src/widgets/icon_data.dart
[ +456 ms] Finished transforming asset at path '/Users/albert/Projects/Playground/asset_transformers_bug/assets/2.0x/image.jpg' (473ms)
[ +311 ms] Expected to find fontFamily for constant IconData with codepoint: 9658.0, but found fontFamily: null. This usually means you are relying on the system font. Alternatively, font families in an IconData class can be provided in the assets section of your pubspec.yaml, or
you are missing "uses-material-design: true".
[   +1 ms] Expected to find fonts for (MaterialIcons, packages/cupertino_icons/CupertinoIcons), but found (MaterialIcons). This usually means you are referring to font families in an IconData class but not including them in the assets section of your pubspec.yaml, are missing the
package
           that would include them, or are missing "uses-material-design: true".
[        ] Running font-subset: /Users/albert/fvm/versions/3.24.0-0.0.pre/bin/cache/artifacts/engine/darwin-x64/font-subset build/web/assets/fonts/MaterialIcons-Regular.otf /Users/albert/fvm/versions/3.24.0-0.0.pre/bin/cache/artifacts/material_fonts/MaterialIcons-Regular.otf,
using codepoints 57490 62832 57706 58332 58727 57496 57694 57695 57657 57882 57504 61453 57634 57498 57926 57704 57491 61061 61060 62834 62833 59283 59282 57499 57500 61069 61068 62842 62841 59291 59290 58011 58012 61575 61576 63348 63349 59797 59798 58372 58370 61930 61927 63708
63705 60157 60154 58771 58189 62328 61752 983402 63526 60555 59975 57502 58814 58813 57846 57862 57686 61764 57402 optional:32
[  +15 ms] Font asset "MaterialIcons-Regular.otf" was tree-shaken, reducing it from 1645184 to 7692 bytes (99.5% reduction). Tree-shaking can be disabled by providing the --no-tree-shake-icons flag when building your app.
[ +688 ms] Persisting file store
[   +5 ms] Done persisting file store
[   +4 ms] Target web_release_bundle failed: Error: User-defined transformation of asset "/Users/albert/Projects/Playground/asset_transformers_bug/assets/image.jpg" failed.
           Asset transformer transformer did not produce an output file.
           Input file provided to transformer: "/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput0.jpg"
           Expected output file at: "/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput1.jpg"
           Full command: /Users/albert/fvm/versions/3.24.0-0.0.pre/bin/cache/dart-sdk/bin/dart run transformer --input=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput0.jpg
           --output=/var/folders/mh/n8gr4_w94sndpqg3619xhxxh0000gn/T/flutter_tools.Us7XSm/image.jpg-transformOutput1.jpg
           stdout:
           
           stderr:
           
           #0      throwToolExit (package:flutter_tools/src/base/common.dart:10:3)
           #1      copyAssets.<anonymous closure> (package:flutter_tools/src/build_system/targets/assets.dart:157:19)
           <asynchronous suspension>
           #2      Future.wait.<anonymous closure> (dart:async/future.dart:534:21)
           <asynchronous suspension>
           #3      copyAssets (package:flutter_tools/src/build_system/targets/assets.dart:128:3)
           <asynchronous suspension>
           #4      WebReleaseBundle.build (package:flutter_tools/src/build_system/targets/web.dart:448:29)
           <asynchronous suspension>
           #5      _BuildInstance._invokeInternal (package:flutter_tools/src/build_system/build_system.dart:875:9)
           <asynchronous suspension>
           #6      Future.wait.<anonymous closure> (dart:async/future.dart:534:21)
           <asynchronous suspension>
           #7      _BuildInstance.invokeTarget (package:flutter_tools/src/build_system/build_system.dart:813:32)
           <asynchronous suspension>
           #8      FlutterBuildSystem.build (package:flutter_tools/src/build_system/build_system.dart:635:16)
           <asynchronous suspension>
           #9      WebBuilder.buildWeb (package:flutter_tools/src/web/compile.dart:92:34)
           <asynchronous suspension>
           #10     BuildWebCommand.runCommand (package:flutter_tools/src/commands/build_web.dart:227:5)
           <asynchronous suspension>
           #11     FlutterCommand.run.<anonymous closure> (package:flutter_tools/src/runner/flutter_command.dart:1408:27)
           <asynchronous suspension>
           #12     AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:153:19)
           <asynchronous suspension>
           #13     CommandRunner.runCommand (package:args/command_runner.dart:212:13)
           <asynchronous suspension>
           #14     FlutterCommandRunner.runCommand.<anonymous closure> (package:flutter_tools/src/runner/flutter_command_runner.dart:420:9)
           <asynchronous suspension>
           #15     AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:153:19)
           <asynchronous suspension>
           #16     FlutterCommandRunner.runCommand (package:flutter_tools/src/runner/flutter_command_runner.dart:364:5)
           <asynchronous suspension>
           #17     run.<anonymous closure>.<anonymous closure> (package:flutter_tools/runner.dart:130:9)
           <asynchronous suspension>
           #18     AppContext.run.<anonymous closure> (package:flutter_tools/src/base/context.dart:153:19)
           <asynchronous suspension>
           #19     main (package:flutter_tools/executable.dart:93:3)
           <asynchronous suspension>


[   +8 ms] Compiling lib/main.dart for the Web... (completed in 15.0s)
[        ] "flutter web" took 15,453ms.
[   +2 ms] Error: Failed to compile application for the Web.

Flutter Doctor output

Doctor output
[!] Flutter (Channel [user-branch], 3.24.0-0.0.pre, on macOS 14.5 23F79 darwin-arm64, locale en-PL)
    ! Flutter version 3.24.0-0.0.pre on channel [user-branch] at /Users/albert/fvm/versions/3.24.0-0.0.pre
      Currently on an unknown channel. Run `flutter channel` to switch to an official channel.
      If that doesn't fix the issue, reinstall Flutter by following instructions at https://flutter.dev/setup.
    ! Upstream repository unknown source is not a standard remote.
      Set environment variable "FLUTTER_GIT_URL" to unknown source to dismiss this error.
    • Framework revision 84b3f0ab79 (13 days ago), 2024-07-03 07:01:05 -0400
    • Engine revision 8274f54f11
    • Dart version 3.5.0 (build 3.5.0-323.0.dev)
    • DevTools version 2.37.0
    • If those were intentional, you can disregard the above warnings; however it is recommended to use "git" directly to perform update checks and upgrades.

[✓] Chrome - develop for the web
    • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

Metadata

Metadata

Assignees

Labels

P1High-priority issues at the top of the work lista: assetsPackaging, accessing, or using assetsa: buildBuilding flutter applications with the toolcustomer: crowdAffects or could affect many people, though not necessarily a specific customer.found in release: 3.22Found to occur in 3.22found in release: 3.24Found to occur in 3.24has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-webWeb applications specificallyr: fixedIssue is closed as already fixed in a newer versionteam-toolOwned by Flutter Tool teamtoolAffects the "flutter" command-line tool. See also t: labels.triaged-toolTriaged by Flutter Tool team

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions