Skip to main content

    SignTool Errors: What Each One Means and How to Fix It

    Every common SignTool error explained: what the hex code means, why hardware-stored keys changed the diagnosis, and the order to check things in.

    MS
    My-SSL Team
    ·
    13 min read
    ·
    Published August 19, 2026
    ·
    Last updated August 19, 2026

    The short answer

    Most SignTool failures are not failures of SignTool. Since June 1, 2023, CA/Browser Forum ballot CSC-17 has required the private key of every publicly trusted code signing certificate to be generated and held in hardware meeting FIPS 140-2 Level 2 or Common Criteria EAL 4+, so the two error classes that now dominate are SignTool cannot reach the key and the timestamp step failed. Read the hex code rather than the sentence: SignerSign() failed is a wrapper, and the HRESULT printed after it is what identifies the cause.

    The four layers a SignTool command passes through, with the provider layer marked as the usual source of errorsA vertical stack of four layers. From the top: the build command that invokes signtool; SignTool itself with the Windows cryptography API, which selects a certificate and calls SignerSign; the cryptographic provider layer, highlighted in gold, which is token middleware or a cloud key storage provider library and is where most errors originate; and at the bottom the hardware that actually holds the private key, either a USB token or a cloud hardware security module. A separate box to the right shows the certificate authority timestamp server, reached over plain HTTP after the signature is made, and labelled as the second independent failure point.Where a signing command actually breaks1. Your build commandsigntool sign /fd SHA256 /tr … app.exe2. SignTool and the Windows crypto APIPicks a certificate, then calls SignerSign()3. CSP or KSP providerToken middleware, or a cloud signing libraryMost errors start here4. The hardware holding the private keyUSB token, on-premise HSM, or cloud HSMCA timestamp serverRFC 3161, over plain HTTPReached after the signatureis made, not beforeSecond failure point
    SignTool is layer two of four. If you spend your time editing the command at layer one, you are usually debugging the wrong layer.

    Why are most SignTool errors not really about SignTool?

    Because SignTool never touches your private key. It asks Windows for a certificate, then asks a cryptographic provider to produce a signature with the key behind that certificate. The provider is separate software — token middleware, or a library supplied by a cloud signing service — and it is where the failure normally happens. SignTool only reports what came back.

    This is a fairly recent shift in what goes wrong. Before June 2023 you could import a PFX file, point /f at it, and the whole provider layer was a file on disk that either existed or did not. Ballot CSC-17 ended that for publicly trusted certificates: the key must now be generated inside hardware meeting FIPS 140-2 Level 2 or Common Criteria EAL 4+, and marked non-exportable. A USB token, an HSM you run, or a CA cloud signing service are the three legitimate homes for it.

    Most of the advice you will find for these errors predates that change, which is why so much of it does not work. Guidance that begins “re-import the PFX with the private key” is answering a question about a world that no longer exists for public code signing. The certificate you are trying to use cannot be re-imported, because it was never exportable in the first place. Whatever is wrong sits in the path between SignTool and the hardware.

    There is a second thing worth knowing before you start. The timestamp request is a separate network call to the certificate authority, made after the signature is produced. It fails for entirely different reasons than signing does, it fails far more often, and its failures are recoverable without re-signing. Half of the confusion in SignTool troubleshooting comes from treating those two steps as one.

    How do you diagnose a SignTool error quickly?

    Run the command again with /debug placed directly after sign, and read what it prints before changing anything. SignTool then lists every certificate it considered and why each one was skipped, which sorts the problem into one of four buckets: nothing was found, something was found but filtered out, a certificate was chosen and the signing call failed, or the file was signed and only the timestamp failed.

    Those four buckets have almost nothing in common, and three of them are fixed somewhere other than the command line. Working out which one you are in takes about thirty seconds and saves the far more common approach of editing flags at random until something changes.

    A decision tree that sorts any SignTool failure into one of four causesThe tree starts by asking whether SignTool listed any candidate certificate when run with the debug flag. If it listed none, the cause is certificate or provider visibility: wrong user account, token not connected, or middleware not installed. If it listed a certificate but rejected all of them, the cause is a selection filter such as a mismatched subject name or a missing code signing extended key usage. If a certificate was chosen but SignerSign failed, the cause is key access, and the hex code identifies which. If the file was signed and only the timestamp failed, the cause is the timestamp path, and the file is already signed. The timestamp branch is highlighted in gold as the one case where nothing needs re-signing.Start with: signtool sign /debug …What did the run reach?Read the output, not the exit codeNo certificates listedWrong user accountToken not connectedMiddleware missingFix: certmgr.msc as thesame account that signsListed,all rejected/n subject mismatchNo code signing EKUExpired certificateFix: select by /sha1thumbprint insteadChosen,SignerSign failed0x80090016 keyset0x80070520 session0x8007000B formatFix: read the hex codein the reference belowSigned,timestamp failed/t vs /tr mismatchProxy blocking HTTPServer busyFix: timestamp separately,the file is already signedThe order mattersEstablish which of the four you are in before changing anything. Three of the four are fixed outside the command line.
    Four branches, four different fixes. Guessing between them is what turns a ten-minute problem into an afternoon.

    One detail that catches people repeatedly: run the diagnostic as the same account that will run the real command. A certificate in your desktop user’s Personal store is invisible to a build service running as NT AUTHORITY\SYSTEM or a dedicated service account, and a command that works perfectly in your own shell will fail in the pipeline for that reason alone. If you are debugging a CI failure, reproduce it under the CI account before you conclude anything.

    What does “No certificates were found that met all the given criteria” mean?

    It means SignTool searched and came back empty. The search is narrower than most people assume: it looks in the Personal certificate store of the account running the command, for certificates that carry the Code Signing extended key usage, have an associated private key, and match whatever selection flag you passed. Failing any one of those conditions produces this message, with no indication of which one failed.

    Work through them in this order, because they get progressively less likely:

    • Is the key reachable at all? For a USB token, that means plugged in and its middleware installed — without the card software, Windows cannot see the certificate, never mind the key. Our guide to SafeNet Authentication Client walks through the four checks that isolate a token-not- detected error. For a cloud signing service, it means the desktop client or provider library is running and authenticated.
    • Is it the right account? Open certmgr.msc as the account that runs SignTool and look under Personal → Certificates. If the certificate is not there, nothing else you do to the command will help.
    • Is your selection filter too tight? /n matches on subject name and is fussy about it. Selecting by thumbprint with /sha1 removes that whole class of problem: copy the value from the certificate’s Details tab, Thumbprint field, and strip the spaces.
    • Is it actually a code signing certificate? A TLS certificate, a document signing certificate, or a self-signed test certificate without the Code Signing EKU will be filtered out. So will an expired one.

    In a reseller support queue this error is overwhelmingly the first one a new customer hits, and the cause is nearly always the first bullet rather than the last: the token arrived, the certificate was collected, and the middleware was never installed. It is worth ruling out before you touch the command at all.

    What does “SignerSign() failed” actually tell you?

    On its own, nothing. SignerSign() is the Windows API that SignTool calls to produce the signature, so this line appears whenever that call returns an error — which covers dozens of unrelated causes. The information is in the two numbers printed after it. They are the same value twice: a signed decimal, and the standard Windows HRESULT in hex. The hex is the part to search for.

    A labelled breakdown of a SignTool error message showing which part carries the diagnostic informationA two-line SignTool error message is shown. The first line, an unexpected internal error has occurred, is labelled as a generic wrapper carrying no information. On the second line, the phrase SignerSign failed is labelled as the Windows API call that returned the error, also generic. The decimal number is labelled as the same value as the hex, expressed as a signed integer. The hex value, highlighted in gold, is labelled as the standard Windows HRESULT and the only part worth searching for.Which part of the error actually tells you somethingSignTool Error: An unexpected internal error has occurred.Error information: "Error: SignerSign() failed." (-2147024885/0x8007000B)Generic wrapper. Says nothing.The Windows API that failed. Appears for dozens of unrelated causes.The HRESULT. This is the part to search for, and the decimal on its left is the same number.
    Searching the sentence returns thousands of unrelated threads. Searching the hex value returns the actual cause.

    Three HRESULTs cover most of what you will see. 0x80090016 means the key set does not exist — the certificate is visible but the private key behind it is not, which on a token means it is unplugged or its middleware is not loaded. 0x80070520 says a specified logon session does not exist, which is the same problem seen from the other side: the key is there, but not reachable from the session the command is running in. 0x8007000B is a format error, and for MSIX or Appx packages it almost always means the publisher name in the manifest does not match the certificate’s subject.

    That last one deserves a note, because the fix is not on the signing side. The manifest’s Publisher attribute has to match the certificate subject exactly, field for field, including the country code — not approximately, and not just the common name. Either edit the manifest to match the certificate, or accept that the certificate you bought decides what your package’s publisher string has to be. Microsoft’s own MSIX troubleshooting guidance points at the same mismatch, and suggests the AppxPackaging operational log in Event Viewer when the message alone is not enough.

    What if SignTool finds the certificate but not the private key?

    Then the certificate and the key have become separated, and you need to tell SignTool which provider holds the key. A certificate in the Windows store is just a public document; the link to the key is a provider reference stored alongside it. If that reference is missing, stale, or points at a provider that is not currently running, you get a key set or logon session error rather than a certificate error.

    For a physical token, the fix is normally to reinstall or restart the token middleware, then re-import the certificate through the vendor’s own tool rather than by double-clicking the file. Importing a .cer by hand creates exactly this situation: the certificate lands in the store with no key association at all.

    For cloud signing, you usually have to name the provider explicitly. The pattern is /csp "<provider name>" /kc <key alias>, where the provider name is the CSP or KSP the service installs and the alias identifies the key inside it — DigiCert KeyLocker documents this shape for its KSP, and Certum’s SimplySign takes the related route of presenting the cloud key as a virtual card reader so that ordinary thumbprint selection works. Which of the two styles applies to you is a property of the service, not of SignTool, so the vendor’s own signing document is the authority.

    If you are hitting this repeatedly on a build server, the real answer is probably a change of delivery model rather than a better command. Physical tokens were designed for a person at a desk, and every workaround for using one unattended is worse than the problem. Cloud signing services and networked HSMs exist precisely because build agents cannot plug anything in; our code signing certificates are available with cloud key storage for that reason. The trade-offs between the two are laid out in our comparison of cloud signing and USB tokens.

    Why does the timestamp server keep failing?

    Nine times out of ten, because the flag and the protocol do not match. SignTool has two timestamp options that are not interchangeable: /tr speaks RFC 3161 and expects /td SHA256 alongside it, while /t speaks the older Authenticode timestamp protocol. Point either one at the other’s endpoint and you get “could not be reached or returned an invalid response”, even though the URL is perfectly reachable in a browser.

    The second cause is the network rather than the command. Timestamp endpoints are plain HTTP, not HTTPS, which is correct — RFC 3161 responses are signed, so the transport does not need to be — but it means outbound filters that allow only port 443 will silently break timestamping while everything else on the build agent works. Public timestamp servers are also genuinely busy at times, and a request that fails now may succeed a minute later.

    Signing and timestamping shown as two separable steps, so a timestamp failure does not require re-signingThe top row shows the combined command: signtool sign with a timestamp flag performs both the signature and the timestamp request in one call, and a failure at the timestamp step still leaves a signed file on disk. The bottom row, highlighted in gold, shows the recovery: signtool timestamp adds an RFC 3161 timestamp to the already signed file, giving an identical result without repeating the signature. An arrow connects the failed timestamp step in the top row to the recovery command below it.A failed timestamp does not undo the signaturesigntool signSignature writtenTimestamp requestFails hereNon-zero exitFile is still signedRecovery: timestamp the existing signaturesigntool timestamp /tr <url> /td SHA256 app.exeIdentical result, no second call to the hardware key
    Worth wiring into a pipeline: retry the timestamp on its own before you retry the whole signing job.

    The practical response is to stop coupling the two steps. If signtool sign reported a timestamp failure, the file on disk is already signed; adding the timestamp afterwards with signtool timestamp /tr <url> /td SHA256 app.exe gives an identical result. In a pipeline, retrying the timestamp alone — with a short backoff, and a fallback server on the second attempt — is both faster and cheaper than repeating a signing call against a rate-limited cloud key.

    Do not be tempted to drop the timestamp to make a red build go green. An untimestamped signature stops validating the day the certificate expires, and what our guide to code signing timestamping describes as a formality is the thing keeping every release you have ever shipped verifiable.

    What happens when the certificate has expired or been revoked?

    An expired certificate cannot sign anything new, and SignTool reports it as “no certificates were found” rather than saying so — the expiry check is part of the selection filter, so the certificate is simply excluded. Files you signed earlier are unaffected as long as they were timestamped: the timestamp records that the signature existed while the certificate was valid, and Windows keeps honouring it.

    Revocation behaves differently, and worse. Where expiry is a clean line in time that a timestamp protects you from, a revocation can be dated to cover signatures made before it, in which case the timestamp does not save them. This is the scenario that makes key compromise so expensive: it is not the next release that is at risk, it is every release still in the field.

    Expiry is also arriving more often than it used to. Under CA/Browser Forum ballot CSC-31, code signing certificates issued on or after March 1, 2026 are capped at 460 days, down from the previous 39-month maximum, so the three-year cycle many teams built their release process around is gone. If your certificate is approaching that line, plan the replacement certificate before the last release of the cycle rather than after the first failed build — validation on a new organisation takes days, not minutes, and a token still has to be shipped if that is your delivery model.

    SignTool error code reference

    These are the HRESULTs that account for most SignTool failures in a hardware-key setup, with what each one means and where the cause usually sits. Match the hex value from your error line against the first column; the message text on its own is not specific enough to go on.

    HRESULTWindows meaningWhat it usually is when signing
    0x8007000BERROR_BAD_FORMATThe file or its manifest is not in the shape the signer expects. For MSIX and Appx packages the usual cause is a publisher name in the manifest that does not match the certificate subject, field for field.
    0x80090016Keyset does not existThe certificate is visible but its private key is not. Token unplugged, middleware not loaded, or the key belongs to a different user profile than the one running SignTool.
    0x80070520A specified logon session does not existThe private key cannot be reached from the current logon session. Classic on build agents and service accounts, and on certificates imported into the wrong certificate context.
    0x80092009CRYPT_E_NO_MATCH — cannot find the requested objectThe object being asked for is not there. On a verify run it usually means the file carries no signature of the type being checked.
    0x80004005E_FAIL — unspecified errorCarries no information at all. Re-run with /debug, and check the provider's own log if you are signing through a cloud service.

    Two named errors do not carry a hex code and are worth listing alongside them. “No file digest algorithm specified” means you are on a SignTool version where /fd is mandatory; add /fd SHA256. “The specified timestamp server either could not be reached or returned an invalid response” is the flag and protocol mismatch covered above, not usually a dead server.

    If your error is not here, the command that resolves it is almost always the same one: signtool sign /debug …. Step by step instructions for a working command, including the flags that changed in recent SDK versions, are in our guide to signing an EXE with SignTool.

    Frequently Asked Questions

    Get instant answers to common questions about SSL certificates and our services.

    Still Have Questions?

    Our SSL experts are available 24/7 to help with any questions about certificates, installation, or technical issues.

    When the fix is the certificate rather than the command

    Some of these errors are not solvable at the command line: an expired certificate, a key stranded on a token nobody can plug into a build agent, or a delivery model that never suited the pipeline it ended up in. Our code signing certificates are issued by Certum and available with cloud key storage as well as a physical token, so unattended signing does not depend on hardware being present at the machine doing the work.

    Related reading