Skip to content

Bug: build_runner fails to cleanup outdated outputs #3875

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
schultek opened this issue Feb 22, 2025 · 10 comments · May be fixed by #3879
Open

Bug: build_runner fails to cleanup outdated outputs #3875

schultek opened this issue Feb 22, 2025 · 10 comments · May be fixed by #3879
Assignees
Labels
type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)

Comments

@schultek
Copy link

I am investigating this build_runner error when using Jaspr. After some digging I found a reproducible setup and think its a general build_runner bug. It boils down to the following:

I have two builders:

  • Builder A reads in .a and generates .b (e.g. main.a -> main.b)
  • Builder B reads in .b and generates .c (e.g. main.b -> main.c)

Builder A has some logic that it only conditionally generates .b files and that condition might change while watching the files (dart run build_runner watch).

When that happens, Builder A no longer outputs main.b. At that point I expect build_runner to also cleanup main.c since Builder B is also no longer executed since it doesn't have any input. However main.c still persists with now outdated contents.

To reproduce do the following steps:

  1. Create a blank dart project.
  2. Add build as a dep and build_runner as a dev dep.
  3. Add the following files:
build.yaml
builders:
  a:
    import: "package:buildtest/builders.dart"
    builder_factories:
      - aBuilder
    build_extensions:
      .a:
        - .b
    auto_apply: all_packages
    build_to: source
    required_inputs: [".a"]
  b:
    import: "package:buildtest/builders.dart"
    builder_factories:
      - bBuilder
    build_extensions:
      .b:
        - .c
    auto_apply: all_packages
    build_to: source
    required_inputs: [".b"]
lib/builders.dart
import 'dart:async';

import 'package:build/build.dart';

Builder aBuilder(BuilderOptions options) => ABuilder();
Builder bBuilder(BuilderOptions options) => BBuilder();

class ABuilder extends Builder {
  @override
  FutureOr<void> build(BuildStep buildStep) async {
    var content = await buildStep.readAsString(buildStep.inputId);
    if (content.contains('on')) {
      await buildStep.writeAsString(buildStep.inputId.changeExtension('.b'), content);
    }
  }

  @override
  Map<String, List<String>> get buildExtensions => {
    '.a': ['.b'],
  };
}

class BBuilder extends Builder {
  @override
  FutureOr<void> build(BuildStep buildStep) async {
    var content = await buildStep.readAsString(buildStep.inputId);
    await buildStep.writeAsString(buildStep.inputId.changeExtension('.c'), content);
  }

  @override
  Map<String, List<String>> get buildExtensions => {
    '.b': ['.c'],
  };
}
lib/test.a
test on
  1. Run dart run build_runner watch -v
  2. See lib/test.b and lib/test.c being generated.
  3. Change lib/test.a to test off
  4. See lib/test.b correctly being removed, but lib/test.c wrongly being still there.

In the real-world case I experienced, BuilderA is a custom builder by Jaspr that generates web/<filename>.dart files that should be compiled to js. BuilderB is ddc_modules from package:build_web_compilers that outputs .ddc.module files for each .dart file. The error occurs in the ddc builder that for each .ddc.module tries to read the respective .dart file, which doesn't exist for an outdated module.

You can reproduce the error by creating a new Jaspr project (jaspr create testapp), starting build_runner watch and removing the @client annotation from e.g. lib/pages/about.dart.


dart --version: Dart SDK version: 3.7.0 (stable) (Wed Feb 5 04:53:58 2025 -0800) on "macos_arm64"
build_runner: ^2.4.15 (latest)
build: ^2.4.2 (latest)

@schultek schultek added the type-bug Incorrect behavior (everything from a crash to more subtle misbehavior) label Feb 22, 2025
@davidmorgan davidmorgan self-assigned this Feb 24, 2025
@davidmorgan
Copy link
Contributor

Thanks!

Do you think this is a regression, or an old issue?

If I broke something recently I should try to figure out why; if it's an older issue it'll need to wait a little longer until the current refactoring is done.

@schultek
Copy link
Author

@davidmorgan I can try to reproduce it with an older build_runner version if that helps. What would be the right version to do that with?

@davidmorgan
Copy link
Contributor

That would be helpful, yes please.

There are a lot of packages :) maybe try

dart pub downgrade build build_config build_modules build_resolvers build_runner build_runner_core build_web_compilers build_test

and see if it picks something sensible?

@schultek
Copy link
Author

schultek commented Feb 24, 2025

It appears to be a longer standing bug.

I could reproduce with Dart 3.5 + build_runner 2.4.8 and with Dart 3.4 + build_runner 2.4.2.
(I also downgraded the other build packages and tried around with lots of different version combinations, but that lead to nothing.)

@jakemac53
Copy link
Contributor

@schultek
Copy link
Author

Yes but not really.

If I simply delete the first file by hand, the rest is removed fine.
But this bug is that the first builder stops generating a file. Then it doesn't propagate.

@jakemac53
Copy link
Contributor

👍 I can reproduce the issue, and yeah it seems specific to whether the output is created based on some condition in the builder, interesting.

@davidmorgan
Copy link
Contributor

Thanks Kilian, thanks Jake :) will see if it's possible to get a fix into the next release, probably a week or two away since a pile of things are mid refactor.

@schultek
Copy link
Author

Hi @davidmorgan, whats the current status of this?

@davidmorgan
Copy link
Contributor

@schultek I think I found the place where it needs fixing; once the performance refactoring release is out I'll try it.

"A week or two away" turned out to be very optimistic :) but now I think the next release really is just a week or two away.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-bug Incorrect behavior (everything from a crash to more subtle misbehavior)
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants