Skip to content

Service Worker: Hash Mismatch #23613

Closed as not planned
Closed as not planned

Description

@manfredsteyer

I'd like to use this to start a discussion based upon a topic I talked about with @gkalpak at ng-conf 2018.

As mentioned in #21288, the service worker implementation checkes the hashes of the cached files and if they don't match, it just serves the data from the network (which is like having no service worker).

The problem is that every proxy on the web can manipulate the files downloaded. This is especially the case for mobile providers that are minifying and inlining a lot of stuff on the fly to save bandwith. But also tools like live-server change the index.html (and so they can be used to reproduce this issue).

As one of the big use cases for PWAs are areas with low bandwith, this is somehow conflicting.

Perhaps one way to solve this is to provide an exchangeable HashCheckStrategy. In cases where I as the programmer wants to take the responsiblity for not checking the hashes in order to bypass this issue, I could write sth like this:

export class BruceWillisHashCheckStrategy implements HashCheckStrategy {
     check(currentHash, expectedHash, fileName) {
         return true;
     }
}

Activity

  1. gkalpak commented on May 2, 2018

    @gkalpak
    Member

    Yes, I've been bitten by this myself and I suspect many others have been/will be too (with or without realizing 😁). It is hard to track down and it would be great if we could come up with an easy to use solution that remained reliable.

    My first thought was to be able to automatically put the hash of a file as a comment (e.g. at the top of the file), so that the SW could read the hash from the file (instead of hashing it itself). This might not work for certain types of files though (e.g. images).

    Having a configurable HashCheckStrategy would be nice iff we could ensure that it is a reliable one (which I don't think we can). Being able to reliably determining file content equality (which is what hash comparison gives us) is essential to the SW's working as expected (and not serving incorrect content).

    Giving users the power to easily mess this fundamental check is very dangerous imo. (E.g. with the "pass all" strategy shown above, you could easily end up being served an old, outdated asset (image, stylesheet, script) along with the latest index.html and app files, with unexpected results.

    @alxhub, any thoughts on that? Do you know/remember what other strategies (other than comparing hashes) have been considered/rejected?

  2. added this to the needsTriage milestone on May 3, 2018
  3. modified the milestones: needsTriage, Backlog on May 11, 2018
  4. modified the milestones: Backlog, needsTriage on May 11, 2018
  5. added
    featureLabel used to distinguish feature request from other issues
    on May 11, 2018
  6. modified the milestones: needsTriage, Backlog on May 11, 2018
  7. d2kx commented on Jun 10, 2018

    @d2kx

    I have run into similar issues when combining SSR (Universal) and Service Workers, as the pre-rendered index.html hash differs from the one in the manifest, making offline support impossible. I currently use the work-around to remove the hash from the index.html before deploying.

  8. vytautas-pranskunas- commented on Jul 6, 2018

    @vytautas-pranskunas-

    @d2kx can you sare some code snippet how you remove it or explain it in more deatils? Is offline possible if you remove hash?

  9. gkalpak commented on Jul 9, 2018

    @gkalpak
    Member

    Hm...actually, I just tried this is worked fine:

    1. Download the finished sample code from the Universal Guide.
    2. Unzipped and installed dependencies (with npm install).
    3. Enabled SW with ng add @angular/pwa --project=angular.io-example.
    4. Built with npm run build:ssr.
    5. Run with npm run serve:ssr.

    SSR works as expected on the first request (before the SW is activated). Once the SW takes over, the non-prerendered index.html is served, but that is OK, since it is served by the SW and doesn't require a round-trip to the server. (Offline mode also works fine.)

    So, SSR speeds up the first request and SW speeds up subsequent requests (and enables offline mode).

    So, that usecase works fine. Using app-shell is a different story. I'll have to investigate that more 😃

  10. vytautas-pranskunas- commented on Jul 9, 2018

    @vytautas-pranskunas-

    Thats a point - SW should be written that way that it cache index.html after SSR and for offline mode uses latest cached one. Because SSR is not only for speed it's main thing is SEO and if index.html is not changing then google spiders cannot gather info ;)

  11. gkalpak commented on Jul 9, 2018

    @gkalpak
    Member

    Actually, there is a cli issue for app-shell+SW. Let's track that specific problem there: angular/angular-cli#8794

  12. 39 remaining items

  13. hqrd commented on Oct 22, 2021

    @hqrd

    I also have an issue with hashes. My index.html has a <script> tag added by Dynatrace RUM and makes my client side hash always invalid. I had to remove the index.html from the ngsw-config.

  14. AaronDovTurkel commented on Oct 25, 2021

    @AaronDovTurkel

    @hqrd if you can get the script tag in the build then,as @gkalpak said, you can regenerate the hash table after the script is injected.

  15. hqrd commented on Oct 25, 2021

    @hqrd

    @hqrd if you can get the script tag in the build then,as @gkalpak said, you can regenerate the hash table after the script is injected.

    I'm doing that already for other files with environment variables, but it doesn't work in this case because the script tag is added after my app is started, and has some changing variables.

  16. hiepxanh commented on Dec 19, 2021

    @hiepxanh
    Contributor

    hello, my service worker have hash missmatch problem, I guess there is facebook causing this error. I have question:

    1. how can I skip facebook url cache on SW?
    2. how to force reload? I mean force update, clear service worker itself
      image
  17. Dador commented on Jan 6, 2022

    @Dador

    I have the same issue, in my case it caused by MITM proxy that client using to block ads (AdGuard for Android). That MITM proxy adds <script>...</script> to index.html and of course hash doesn't matches after such manipulations. Because it's happens on client side there is no way to predict new hash.

    Maybe it's good idea to add the hash inside file contents? That way we can confirm that we dowloaded latest version of the file and still allow some modifications (especially the ones we can't control).

  18. antal-huck commented on Jul 14, 2022

    @antal-huck

    @mich71095 Thanks for your comment. I had the same issue and changing the transfer type to binary solved the problem.

    Whenever I copied over e.g. index.html and main.js to the web server, the ServiceWorkers did not register updates, and when I copied a new ngsw.json, then I received the VersionInstallationFailedEvent due to hash mismatches.

  19. webdeveloperninja commented on Sep 8, 2022

    @webdeveloperninja

    Our release pipeline does a token replace on a configuration file in the assets folder to handle build once deploy to multiple environments. Updating the file changes the sha hash in the ngsw.json hashTables object. This node script ended up working after running this after the token replace task. This issue helped me solve my problem. Was stuck for a good 3 days.

    const crypto = require('crypto');
    const fs = require('fs');
    
    var getSHA1ofJSON = function(input){
      const hash = crypto.createHash('sha1');
      hash.update(input);
      
      return hash.digest('hex');
    }
    
    const args = getArgs();
    
    const pathToSettings = args.pathToSettings;
    const pathToNgswJson = args.pathToNgswJson;
    
    let ngsw = JSON.parse(fs.readFileSync(pathToNgswJson));
    
    const fileBuffer = fs.readFileSync(pathToSettings);
    const sha1 = getSHA1ofJSON(fileBuffer);
    
    ngsw.hashTable['/assets/settings.tokenize.json'] = sha1;
    
    fs.writeFileSync(pathToNgswJson, JSON.stringify(ngsw));
    
  20. yoazerty commented on Nov 14, 2022

    @yoazerty

    Had the same issue as @hqrd with Dynatrace adding script tag in my index.html file, causing the Service Worker hash mismatch problem... searched for hours...

  21. bjornharvold commented on Jul 10, 2023

    @bjornharvold

    In my case, when I turned off Cloudflare content optimizations, Service Worker started to work again like magic; just like @manfredsteyer stated in the ticket mentioned above.

    Screenshot 2023-07-10 at 18 45 15
  22. sannyjacobsson commented on Apr 11, 2024

    @sannyjacobsson

    @hqrd if you can get the script tag in the build then,as @gkalpak said, you can regenerate the hash table after the script is injected.

    I'm doing that already for other files with environment variables, but it doesn't work in this case because the script tag is added after my app is started, and has some changing variables.

    @hqrd Did you ever solve your issue?

  23. hqrd commented on Apr 12, 2024

    @hqrd

    @hqrd if you can get the script tag in the build then,as @gkalpak said, you can regenerate the hash table after the script is injected.

    I'm doing that already for other files with environment variables, but it doesn't work in this case because the script tag is added after my app is started, and has some changing variables.

    @hqrd Did you ever solve your issue?

    Yes, by playing with the /node_modules/.bin/ngsw-config in the Dockerfile, to track updated env variables, instead of the index.html, and update the ngsw-config accordingly yes. Basically what @webdeveloperninja commented.

  24. JeanMeche commented on Aug 29, 2025

    @JeanMeche
    Member

    With #63364 we've announced that the service-worker package in now in maintenance mode and will not receive feature PRs and feature requests.

    The message is also visible here: https://angular.dev/ecosystem/service-workers

  25. angular-automatic-lock-bot commented on Sep 29, 2025

    @angular-automatic-lock-bot

    This issue has been automatically locked due to inactivity.
    Please file a new issue if you are encountering a similar or related problem.

    Read more about our automatic conversation locking policy.

    This action has been performed automatically by a bot.

  26. locked and limited conversation to collaborators on Sep 29, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    area: service-workerIssues related to the @angular/service-worker packagefeatureLabel used to distinguish feature request from other issuesfeature: under considerationFeature request for which voting has completed and the request is now under consideration

    Type

    No type

    Projects

    No projects

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions