diff --git a/core/modules/workflows/src/Plugin/WorkflowTypeBase.php b/core/modules/workflows/src/Plugin/WorkflowTypeBase.php
index 6f4e9ceeed..9f2e6770fb 100644
--- a/core/modules/workflows/src/Plugin/WorkflowTypeBase.php
+++ b/core/modules/workflows/src/Plugin/WorkflowTypeBase.php
@@ -267,7 +267,7 @@ public function getTransitions(array $transition_ids = NULL) {
   }
 
   /**
-   * Sort states or transitions by weight and label.
+   * Sort states or transitions by weight, label, and key.
    *
    * @param \Drupal\workflows\StateInterface[]|\Drupal\workflows\TransitionInterface[] $objects
    *   Objects to multi-sort.
@@ -277,15 +277,23 @@ public function getTransitions(array $transition_ids = NULL) {
    */
   protected static function labelWeightMultisort($objects) {
     if (count($objects) > 1) {
+      // Separate weights, labels, and keys into arrays.
       $weights = $labels = [];
+      $keys = array_keys($objects);
       foreach ($objects as $id => $object) {
         $weights[$id] = $object->weight();
         $labels[$id] = $object->label();
       }
+      // Sort weights, labels, and keys in the same order as each other.
       array_multisort(
         $weights, SORT_NUMERIC, SORT_ASC,
-        $labels, SORT_NATURAL, SORT_ASC
+        $labels, SORT_NATURAL, SORT_ASC,
+        $keys
       );
+      // Combine keys and weights to make sure the weights are keyed with the
+      // correct keys.
+      $weights = array_combine($keys, $weights);
+      // Return the objects sorted by weight.
       return array_replace($weights, $objects);
     }
     return $objects;
diff --git a/core/modules/workflows/tests/modules/workflow_type_test/src/Form/ComplexTestTypeStateForm.php b/core/modules/workflows/tests/modules/workflow_type_test/src/Form/ComplexTestTypeStateForm.php
index 679b314d19..a466a7d571 100644
--- a/core/modules/workflows/tests/modules/workflow_type_test/src/Form/ComplexTestTypeStateForm.php
+++ b/core/modules/workflows/tests/modules/workflow_type_test/src/Form/ComplexTestTypeStateForm.php
@@ -22,7 +22,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
       '#type' => 'textfield',
       '#title' => $this->t('Extra'),
       '#description' => $this->t('Extra information added to state'),
-      '#default_value' => isset($configuration['states'][$state->id()]['extra']) ? $configuration['states'][$state->id()]['extra'] : '',
+      '#default_value' => $state && isset($configuration['states'][$state->id()]['extra']) ? $configuration['states'][$state->id()]['extra'] : '',
     ];
     return $form;
   }
diff --git a/core/modules/workflows/tests/modules/workflow_type_test/src/Form/ComplexTestTypeTransitionForm.php b/core/modules/workflows/tests/modules/workflow_type_test/src/Form/ComplexTestTypeTransitionForm.php
index 45e15139b9..a88306c750 100644
--- a/core/modules/workflows/tests/modules/workflow_type_test/src/Form/ComplexTestTypeTransitionForm.php
+++ b/core/modules/workflows/tests/modules/workflow_type_test/src/Form/ComplexTestTypeTransitionForm.php
@@ -22,7 +22,7 @@ public function buildConfigurationForm(array $form, FormStateInterface $form_sta
       '#type' => 'textfield',
       '#title' => $this->t('Extra'),
       '#description' => $this->t('Extra information added to transition'),
-      '#default_value' => isset($configuration['transitions'][$transition->id()]['extra']) ? $configuration['transitions'][$transition->id()]['extra'] : '',
+      '#default_value' => $transition && isset($configuration['transitions'][$transition->id()]['extra']) ? $configuration['transitions'][$transition->id()]['extra'] : '',
     ];
     return $form;
   }
diff --git a/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php b/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php
index fcbcbd0448..886750161c 100644
--- a/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php
+++ b/core/modules/workflows/tests/src/Functional/WorkflowUiTest.php
@@ -293,4 +293,29 @@ public function testWorkflowConfigurationForm() {
     $this->assertEquals('Extra global settings', $workflow->getTypePlugin()->getConfiguration()['example_setting']);
   }
 
+  /**
+   * Test a workflow, state, and transition can have a numeric ID and label.
+   */
+  public function testNumericIds() {
+    $this->drupalLogin($this->createUser(['administer workflows']));
+    $this->drupalGet('admin/config/workflow/workflows');
+    $this->clickLink('Add workflow');
+    $this->submitForm(['label' => 123, 'id' => 123, 'workflow_type' => 'workflow_type_complex_test'], 'Save');
+
+    $this->assertSession()->addressEquals('admin/config/workflow/workflows/manage/123/add_state');
+
+    $this->submitForm(['label' => 456, 'id' => 456], 'Save');
+    $this->assertSession()->pageTextContains('Created 456 state.');
+
+    $this->clickLink('Add a new transition');
+    $this->submitForm(['id' => 789, 'label' => 789, 'from[456]' => 456, 'to' => 456], 'Save');
+    $this->assertSession()->pageTextContains('Created 789 transition.');
+
+    $workflow = $this->container->get('entity_type.manager')->getStorage('workflow')->loadUnchanged(123);
+    $this->assertEquals(123, $workflow->id());
+    $this->assertEquals(456, $workflow->getTypePlugin()->getState(456)->id());
+    $this->assertEquals(789, $workflow->getTypePlugin()->getTransition(789)->id());
+    $this->assertEquals(456, $workflow->getTypePlugin()->getTransition(789)->to()->id());
+  }
+
 }
diff --git a/core/modules/workflows/tests/src/Unit/WorkflowTest.php b/core/modules/workflows/tests/src/Unit/WorkflowTest.php
index 4d28ab6cb4..8cf449367c 100644
--- a/core/modules/workflows/tests/src/Unit/WorkflowTest.php
+++ b/core/modules/workflows/tests/src/Unit/WorkflowTest.php
@@ -117,6 +117,27 @@ public function testGetStates() {
     $this->assertArrayEquals([], array_keys($workflow->getTypePlugin()->getStates([])));
   }
 
+  /**
+   * Test numeric IDs when added to a workflow.
+   */
+  public function testNumericIdSorting() {
+    $workflow = new Workflow(['id' => 'test', 'type' => 'test_type'], 'workflow');
+    $workflow_type = $workflow->getTypePlugin();
+
+    $workflow_type->addState('1', 'One');
+    $workflow_type->addState('2', 'Two');
+    $workflow_type->addState('3', 'ZZZ');
+    $workflow_type->addState('4', 'AAA');
+
+    $workflow_type->setStateWeight('1', 1);
+    $workflow_type->setStateWeight('2', 2);
+    $workflow_type->setStateWeight('3', 3);
+    $workflow_type->setStateWeight('4', 3);
+
+    // Ensure numeric states are correctly sorted by weight first, label second.
+    $this->assertEquals([1, 2, 4, 3], array_keys($workflow_type->getStates()));
+  }
+
   /**
    * @covers ::getStates
    */
