locked
BackgroundDownloader: 0x80070565 - JavaScript runtime error: The maximum number of secrets that may be stored in a single system has been exceeded.

    Question

  • There seems to be a bug in BackgroundDownloader credential management. For the first few downloads it works like expected. But after a while the downloader throws an exception. Afterwards it is not possible to download files. Uninstall and reinstall the app does not help.

    var cred = new Windows.Security.Credentials.PasswordCredential('x', 'x', 'x');
     
    for (var i = 0; i < 200; i++) {
        Windows.Storage.KnownFolders.videosLibrary.createFileAsync("test.png", Windows.Storage.CreationCollisionOption.generateUniqueName).then(
            function (storageFile) {
                var uri = Windows.Foundation.Uri('http://wiki.xbmc.org/images/thumb/b/b4/Xbmc_remote_win8_widelogo.png/250px-Xbmc_remote_win8_widelogo.png');
     
                var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
     
                // Set authentication header
                downloader.serverCredential = cred;
     
                // Create a new download operation.
                var downloadOperation = downloader.createDownload(uri, storageFile);
     
                // Start the download and persist the promise to be able to cancel the download.
                return downloadOperation.startAsync();
            }
        ).then(
            function (r) { },
            function (r) { }
        );

    The same code written in c# works fine. The exception occurs only with apps written in javascript.

    Any idea?


    • Edited by Abdruggi Monday, December 16, 2013 7:58 AM
    Sunday, December 15, 2013 10:07 PM

Answers

  • Hey There.   You have two issues.  First you have gotten the machine into a state where you can no longer call createDownload for your  URI.  To resolve this delete the .vcrd and .vsch files for your application from the following location:

    C:\Users\YOURNAME\AppData\Local\Microsoft\Vault\4BF4C442-9B8A-41A0-B380-DD4A704DDB28

    There is no easy way to determine which files belong to your application. You should see around 20 files with same date/timestamp from when you last ran your application to see the issue.

    Once the files are deleted, stop/start the vault svc:

    net stop vaultsvc

    net start vaultsvc

    The sample code you sent is not correct.  I am not sure if this accurately represents your real application.   So I will speak to the sample application here.  The sample application runs into this problem because you are starting multiple downloads for the same URI at the same time. 

    Here is a code snippet where you can start one download then create the next download for the same URI when that download completes or errors out.

    downloadFile: function () {
        var that = this;
        var cred = new Windows.Security.Credentials.PasswordCredential('', '', '');
        var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
        // Set authentication header
        downloader.serverCredential = cred;
    
        Windows.Storage.KnownFolders.videosLibrary.createFileAsync("test.jpg", Windows.Storage.CreationCollisionOption.generateUniqueName).done(
                function (storageFile) {
                    var uri = Windows.Foundation.Uri('http://uri/to.jpg/');
    
    
                    // Create a new download operation.
                    var downloadOperation = downloader.createDownload(uri, storageFile);
    
                    // Start the download and persist the promise to be able to cancel the download.
                    downloadOperation.startAsync().done(
                        function complete() {
                            if (cntr < 50) { cntr++; that.downloadFile();}
                        },
                        function error() {
                            if (cntr < 50) { cntr++; that.downloadFile(); }
                        })
                }
            );
    },
    
    _itemInvoked: function (args) {
        this.downloadFile();
    }

    In general, the credential file is created when the download starts, and should be deleted when it finishes.  Since you are creating 200 before maybe the first one finishes you were seeing this error.


    Bret Bentzinger (MSFT) @awehellyeah


    Thursday, December 19, 2013 11:01 PM
    Moderator

All replies

  • Open Credential Manager and see how may stored passwords you have in there, where they came from etc...


    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Monday, December 16, 2013 8:06 PM
    Moderator
  • Hi Jeff,

    • 24 passwords
    • Skydrive, Twitter, Facebook, ....

    No entry has been created by my app.


    • Edited by Abdruggi Tuesday, December 17, 2013 9:57 PM
    Tuesday, December 17, 2013 5:13 PM
  • Can you create a simple project that does nothing more than create the problem and post it to SkyDrive?

    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Tuesday, December 17, 2013 7:39 PM
    Moderator
  • Thanks for your help. A small demo project is available on skydrive. I have written a message (including the link) using the contact form on your blog http://blogs.msdn.com/jpsanders

    The app will throw an exception after downloading the first few files. Then no further downloads are possible. Even a reboot doesn't help.

    • Edited by Abdruggi Tuesday, December 17, 2013 10:02 PM
    Tuesday, December 17, 2013 9:52 PM
  • I think it is a Windows 8.1 related problem. The same code on Windows 8 works like a charm.
    Wednesday, December 18, 2013 10:31 AM
  • Thank you very much for your help identifying this!  I will let you know what I discover!


    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Wednesday, December 18, 2013 1:22 PM
    Moderator
  • Instead of setting the serverCredential a can manually set the authentication header. Than it works.

    var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
    downloader.setRequestHeader('Authorization', "Basic XYZ");

    Wednesday, December 18, 2013 5:31 PM
  • Great hint thanks.  For basic auth that will work but for other schemes no.  I have a co-worker looking at your repro now.

    Jeff Sanders (MSFT)

    @jsandersrocks - Windows Store Developer Solutions @WSDevSol
    Getting Started With Windows Azure Mobile Services development? Click here
    Getting Started With Windows Phone or Store app development? Click here
    My Team Blog: Windows Store & Phone Developer Solutions
    My Blog: Http Client Protocol Issues (and other fun stuff I support)

    Wednesday, December 18, 2013 5:34 PM
    Moderator
  • There seems to be another problem with backgrounddownloader in combination with winjs.xhr and/or httpclient. I was able to fix that by manually clearing the cached credentials. I will try to create a sample project and upload it to skydrive.

    document.execCommand('ClearAuthenticationCache', false);
    

    Wednesday, December 18, 2013 5:53 PM
  • Hey There.   You have two issues.  First you have gotten the machine into a state where you can no longer call createDownload for your  URI.  To resolve this delete the .vcrd and .vsch files for your application from the following location:

    C:\Users\YOURNAME\AppData\Local\Microsoft\Vault\4BF4C442-9B8A-41A0-B380-DD4A704DDB28

    There is no easy way to determine which files belong to your application. You should see around 20 files with same date/timestamp from when you last ran your application to see the issue.

    Once the files are deleted, stop/start the vault svc:

    net stop vaultsvc

    net start vaultsvc

    The sample code you sent is not correct.  I am not sure if this accurately represents your real application.   So I will speak to the sample application here.  The sample application runs into this problem because you are starting multiple downloads for the same URI at the same time. 

    Here is a code snippet where you can start one download then create the next download for the same URI when that download completes or errors out.

    downloadFile: function () {
        var that = this;
        var cred = new Windows.Security.Credentials.PasswordCredential('', '', '');
        var downloader = new Windows.Networking.BackgroundTransfer.BackgroundDownloader();
        // Set authentication header
        downloader.serverCredential = cred;
    
        Windows.Storage.KnownFolders.videosLibrary.createFileAsync("test.jpg", Windows.Storage.CreationCollisionOption.generateUniqueName).done(
                function (storageFile) {
                    var uri = Windows.Foundation.Uri('http://uri/to.jpg/');
    
    
                    // Create a new download operation.
                    var downloadOperation = downloader.createDownload(uri, storageFile);
    
                    // Start the download and persist the promise to be able to cancel the download.
                    downloadOperation.startAsync().done(
                        function complete() {
                            if (cntr < 50) { cntr++; that.downloadFile();}
                        },
                        function error() {
                            if (cntr < 50) { cntr++; that.downloadFile(); }
                        })
                }
            );
    },
    
    _itemInvoked: function (args) {
        this.downloadFile();
    }

    In general, the credential file is created when the download starts, and should be deleted when it finishes.  Since you are creating 200 before maybe the first one finishes you were seeing this error.


    Bret Bentzinger (MSFT) @awehellyeah


    Thursday, December 19, 2013 11:01 PM
    Moderator
  • You should also make sure when your application starts up you re-attach to any background tasks your application started.  This is discussed in the remarks section of the DownloadOperation class.  Here is some sample code you can run at application startup to cancel any pending downloads. 

        app.addEventListener("activated", function (args) {
            if (args.detail.kind === activation.ActivationKind.launch) {
                if (args.detail.previousExecutionState !== activation.ApplicationExecutionState.terminated) {
                    // TODO: This application has been newly launched. Initialize
                    // your application here.
                    var iter = Windows.Networking.BackgroundTransfer.BackgroundDownloader.getCurrentDownloadsAsync().done(
                        function (downloads) {
                            downloads.forEach(function (item) {
                                var download = item.attachAsync();
                                download.cancel();
                            });
                        });
    
                } else {
                    // TODO: This application has been reactivated from suspension.
                    // Restore application state here.
                }
    .
    .
    .
    


    Bret Bentzinger (MSFT) @awehellyeah

    Thursday, December 19, 2013 11:38 PM
    Moderator
  • Hi Bret, thank you very much for your help. This was not my real app code. Only a quick example jeff was asking for. I am using backgrounddownloads to store live time images at app startup. It was working fine for the first few week. But then I got the exception.

    Thanks for your example. I will rewrite my code and queue the downloads.


    • Edited by Abdruggi Thursday, December 19, 2013 11:59 PM
    Thursday, December 19, 2013 11:55 PM
  • Can't believe I did that.  :) Changed it, and thanks for the catch!

    Bret Bentzinger (MSFT) @awehellyeah

    Thursday, December 19, 2013 11:58 PM
    Moderator
  • Do I always have to manually queue my downloads (different files) or can I start a small amount of downloads in parallel and windows will handle that?

    If a download is in progress or paused at the time of uninstalling an app, will windows remove the vault entry?

    Friday, December 20, 2013 8:02 AM
  • You should be able to queue up a LOT of downloads to different URI's.  They just shouldn't be to the same URI. I am not sure of the limit, but have heard of numbers up to 1000 in other forum posts.

    State should be cleaned up and your downloads cancelled when the application is un-installed.


    Bret Bentzinger (MSFT) @awehellyeah

    Friday, December 20, 2013 6:54 PM
    Moderator