Config entity form fails to load entity I have a custom config entity modelled closely on the example documentation and example module.  The example module works fine on my site, my code does not, and I can't see the difference.

What works


Show an empty list of config entities with an add button.
Add a config entity and check it exists via "drush cget".


What fails


In my edit settings form (extends EntityForm), $this->entity has null/default values exactly as if I were adding a new entry.  It does not load the actual entity. It does not perform validation (if I pass a URL /admin/config/content/rrssb/BADPARAM that doesn't map to an existing entity I still see a page, whereas if I do the same test with the example code, I get a 403 error).
In my listing page (extends ConfigEntityListBuilder), if an entity exists I get an error - for some reason the list builder fails to pass the id (machine name) from the entity when building the route.



  Symfony\Component\Routing\Exception\MissingMandatoryParametersException:
  Some mandatory parameters are missing ("button_set") to generate a URL for
  route "entity.rrssb_button_set.edit_form". in
  Drupal\Core\Routing\UrlGenerator->doGenerate() (line 180 of
  core/lib/Drupal/Core/Routing/UrlGenerator.php).


Details

/**
 * Defines the RRSSB button set entity.
 *
 * @ConfigEntityType(
 *   id = "rrssb_button_set",
 *   label = @Translation("RRSSB Button Set"),
 *   handlers = {
 *     "list_builder" = "Drupal\rrssb\RRSSBListBuilder",
 *     "form" = {
 *       "add" = "Drupal\rrssb\Form\RRSSBSettingsForm",
 *       "edit" = "Drupal\rrssb\Form\RRSSBSettingsForm",
 *       "delete" = "Drupal\rrssb\Form\RRSSBDeleteForm",
 *     }
 *   },
 *   config_prefix = "button_set",
 *   admin_permission = "administer rrssb",
 *   entity_keys = {
 *     "id" = "id",
 *     "label" = "label"
 *   },
 *   links = {
 *     "edit-form" = "/admin/config/content/rrssb/{button_set}",
 *     "delete-form" = "/admin/config/content/rrssb/{button_set}/delete",
 *     "collection" = "/admin/config/content/rrssb"
 *   }
 * )
 */


rrssb.routing.yml

entity.rrssb_button_set.collection:
  path: '/admin/config/content/rrssb'
  defaults:
    _entity_list: 'rrssb_button_set'
    _title: 'Ridiculously Responsive Social Sharing Buttons'
  requirements:
    _permission: 'administer rrssb'

entity.rrssb_button_set.add_form:
  path: '/admin/config/content/rrssb/add'
  defaults:
    _entity_form: 'rrssb_button_set.add'
    _title: 'Add RRSSB Button Set'
  requirements:
    _permission: 'administer rrssb'

entity.rrssb_button_set.edit_form:
  path: '/admin/config/content/rrssb/{button_set}'
  defaults:
    _entity_form: 'rrssb_button_set.edit'
    _title: 'Edit RRSSB Button Set'
  requirements:
    _permission: 'administer rrssb'

entity.rrssb_button_set.delete_form:
  path: '/admin/config/content/rrssb/{button_set}/delete'
  defaults:
    _entity_form: 'rrssb_button_set.delete'
    _title: 'Delete RRSSB Button Set'
  requirements:
    _permission: 'administer rrssb'


Help requested

Please can an expert suggest what I'm likely to be missing, or at least help me understand where to look?

In particular, what mechanism (Drupal class/code file) loads the config entry or generates a 403 if it is not found?

The relevant code in my own module spans several files, so I've not pasted it all here, but could upload specific snippets if asked.
Looks like the id key isn’t matching the router parameter defined in the routing file. It should be either button_set or rrssb_button_set, depending on which one is right. Get that fixed and clear the cache and it should work.