Webform pages break when accessing with token

Created on 16 June 2025, 21 days ago

Problem/Motivation

When editing an existing draft submission via a token link, Webform pagination breaks. Specifically, the "Previous" button incorrectly appears on the first page of the form.

Steps to reproduce

  1. Install webform module
  2. Import the following webform configuration (2 wizard pages with checkboxes)
    uuid: 1dda44d2-acaa-464a-b36f-de901d6762a3
    langcode: en
    status: open
    dependencies: {  }
    weight: 0
    open: null
    close: null
    uid: 1
    template: false
    archive: false
    id: contact
    title: Contact
    description: ''
    categories: {  }
    elements: |-
      1:
        '#type': webform_wizard_page
        '#title': '1'
        test:
          '#type': checkbox
          '#title': Test
      2:
        '#type': webform_wizard_page
        '#title': '2'
        test_2:
          '#type': checkbox
          '#title': 'test 2'
    css: ''
    javascript: ''
    settings:
      ajax: false
      ajax_scroll_top: form
      ajax_progress_type: ''
      ajax_effect: ''
      ajax_speed: null
      page: true
      page_submit_path: ''
      page_confirm_path: ''
      page_theme_name: ''
      form_title: both
      form_submit_once: false
      form_open_message: ''
      form_close_message: ''
      form_exception_message: ''
      form_previous_submissions: true
      form_confidential: false
      form_confidential_message: ''
      form_disable_remote_addr: false
      form_convert_anonymous: false
      form_prepopulate: false
      form_prepopulate_source_entity: false
      form_prepopulate_source_entity_required: false
      form_prepopulate_source_entity_type: ''
      form_unsaved: false
      form_disable_back: false
      form_submit_back: false
      form_disable_autocomplete: false
      form_novalidate: false
      form_disable_inline_errors: false
      form_required: false
      form_autofocus: false
      form_details_toggle: false
      form_reset: false
      form_access_denied: default
      form_access_denied_title: ''
      form_access_denied_message: ''
      form_access_denied_attributes: {  }
      form_file_limit: ''
      form_attributes: {  }
      form_method: ''
      form_action: ''
      share: false
      share_node: false
      share_theme_name: ''
      share_title: true
      share_page_body_attributes: {  }
      submission_label: ''
      submission_exception_message: ''
      submission_locked_message: ''
      submission_log: false
      submission_excluded_elements: {  }
      submission_exclude_empty: false
      submission_exclude_empty_checkbox: false
      submission_views: {  }
      submission_views_replace: {  }
      submission_user_columns: {  }
      submission_user_duplicate: false
      submission_access_denied: default
      submission_access_denied_title: ''
      submission_access_denied_message: ''
      submission_access_denied_attributes: {  }
      previous_submission_message: ''
      previous_submissions_message: ''
      autofill: false
      autofill_message: ''
      autofill_excluded_elements: {  }
      wizard_progress_bar: true
      wizard_progress_pages: false
      wizard_progress_percentage: false
      wizard_progress_link: false
      wizard_progress_states: false
      wizard_start_label: ''
      wizard_preview_link: false
      wizard_confirmation: true
      wizard_confirmation_label: ''
      wizard_auto_forward: true
      wizard_auto_forward_hide_next_button: false
      wizard_keyboard: true
      wizard_track: ''
      wizard_prev_button_label: ''
      wizard_next_button_label: ''
      wizard_toggle: false
      wizard_toggle_show_label: ''
      wizard_toggle_hide_label: ''
      wizard_page_type: container
      wizard_page_title_tag: h2
      preview: 0
      preview_label: ''
      preview_title: ''
      preview_message: ''
      preview_attributes: {  }
      preview_excluded_elements: {  }
      preview_exclude_empty: true
      preview_exclude_empty_checkbox: false
      draft: all
      draft_multiple: true
      draft_auto_save: false
      draft_saved_message: ''
      draft_loaded_message: ''
      draft_pending_single_message: ''
      draft_pending_multiple_message: ''
      confirmation_type: page
      confirmation_url: ''
      confirmation_title: ''
      confirmation_message: ''
      confirmation_attributes: {  }
      confirmation_back: true
      confirmation_back_label: ''
      confirmation_back_attributes: {  }
      confirmation_exclude_query: false
      confirmation_exclude_token: false
      confirmation_update: false
      limit_total: null
      limit_total_interval: null
      limit_total_message: ''
      limit_total_unique: false
      limit_user: null
      limit_user_interval: null
      limit_user_message: ''
      limit_user_unique: false
      entity_limit_total: null
      entity_limit_total_interval: null
      entity_limit_user: null
      entity_limit_user_interval: null
      purge: none
      purge_days: null
      results_disabled: false
      results_disabled_ignore: false
      results_customize: false
      token_view: false
      token_update: false
      token_delete: false
      serial_disabled: false
    access:
      create:
        roles:
          - anonymous
          - authenticated
        users: {  }
        permissions: {  }
      view_any:
        roles: {  }
        users: {  }
        permissions: {  }
      update_any:
        roles: {  }
        users: {  }
        permissions: {  }
      delete_any:
        roles: {  }
        users: {  }
        permissions: {  }
      purge_any:
        roles: {  }
        users: {  }
        permissions: {  }
      view_own:
        roles: {  }
        users: {  }
        permissions: {  }
      update_own:
        roles: {  }
        users: {  }
        permissions: {  }
      delete_own:
        roles: {  }
        users: {  }
        permissions: {  }
      administer:
        roles: {  }
        users: {  }
        permissions: {  }
      test:
        roles: {  }
        users: {  }
        permissions: {  }
      configuration:
        roles: {  }
        users: {  }
        permissions: {  }
    handlers:
      debug:
        id: debug
        handler_id: debug
        label: Debug
        notes: ''
        status: true
        conditions: {  }
        weight: 0
        settings:
          format: yaml
          submission: false
    variants: {  }
    
  3. Create a node and embed the webform (via block or Layout Builder)
  4. Access the page and save a submission as Draft.
  5. Go to /admin/structure/webform/manage/test_page/results/submissions and click on the submission ID (using the token URL to edit the draft).
  6. The issue occurs - the first page incorrectly shows the Previous button.

Proposed resolution

The issue is caused by the following methods returning an integer instead of a string or NULL as expected. This breaks strict comparisons in Webform’s pagination logic:

  • \Drupal\webform\Utility\WebformArrayHelper::getFirstKey
  • \Drupal\webform\Utility\WebformArrayHelper::getLastKey
  • \Drupal\webform\Utility\WebformArrayHelper::getKey
  • \Drupal\webform\WebformSubmissionForm::getCurrentPage

These functions should consistently return either a string key or NULL, but never an integer.
The solution is to update these methods to cast array keys to string where applicable, ensuring consistency with the expected return types declared in their docblocks and usage throughout Webform.

πŸ› Bug report
Status

Active

Version

6.3

Component

Code

Created by

πŸ‡§πŸ‡·Brazil hfernandes

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Comments & Activities

Production build 0.71.5 2024