Anonymous user cache issue We're having a problem with caching that is affecting anonymous users.

We have a form in a block that when the user fills out the form, they are able to download a PDF. We hide the block on pages where we don't want this PDF download form to appear. Ideally the block is hidden, if no PDF is available for a particular page, but the block is being cached and displayed regardless the of the actual page. This only is a problem for anonymous users. Logged in users do not have the problem of the seemingly cached PDF download blocks appearing on the wrong pages.

For example after clearing the cache, somebody first visits page A with a PDF available, then that PDF download form block is being cached and the cached version is also displayed for page B which does not have a PDF download.

Same vice versa, if you visit Page B first, than the block is being cached with it's attribute display:none, and it will not be displayed for Page A either
Basically, we need the visibility to be re-evaluated on each page load.

We're fairly certain it's a cache issue as when we inspect the live rendered code we can see the block IDs being mixed up on the page.
For example: we'll see a body-tag includes a class "node-164", it's node 164 and the Download the PDF includes a class "PDF-node-205", so it's the cached version for node 205, it also includes the filename as a CSS classname, it's clearly the block for a different page node.

We've tried disabling the page cache, dynamic cache, and the twig cache and we're still having the same problem. And again it is only happens for anonymous users, logged in users do not see these cached blocks appearing on the wrong pages.

Has anyone run into this or know of another caching method that Drupal may be using that we're not aware of?
If I understand correctly, it is okay for the block to be cached, but each path/URL can have its own "version" of the form, right? In that case, you need to inform Drupal that this block changes depending on the current path/URL. Drupal 8 introduced the concept of "cache contexts" to do that. The cache context defines the external factors by which the return value can vary.

Now that you know this, you'll notice that this question is pretty similar to yours.

As documented in the change record, blocks can define their cache context by overriding the getCacheContexts() method from the BlockCase class. Overriding that method would probably look like this in your block class:

/**
 * {@inheritdoc}
 */
public function getCacheContexts() {
  return Cache::mergeContexts(parent::getCacheContexts(), ['url.path']);
}


As you  can see I'm using the url.path context here. A list of contexts provided by Drupal core can be found in the documentation.