octobercms/october · error · Error

Inspector surface unique ID should be defined.

Error message

Inspector surface unique ID should be defined.

What it means

The second ReportDataPaginationParams constructor check: `$currentPage` must be zero or a positive integer (page indexes are zero-based here, as the docblock 'current page index' indicates). Negative page values would produce negative offsets, so the constructor throws this ApplicationException for anything below 0.

Solutions

  1. Clamp the page index to >= 0 before constructing, e.g. `max(0, (int) $request->input('page', 1) - 1)`.
  2. Use a plain default of 0 for the first page instead of -1 sentinels.
  3. Validate user-supplied page parameters (integer, >= 1 in 1-based form) at the request boundary.

Example fix

// before
$page = (int) array_get($params, 'page', 0) - 1;
new ReportDataPaginationParams(20, $page);

// after
$page = max(0, (int) array_get($params, 'page', 1) - 1);
new ReportDataPaginationParams(20, $page);
Defensive patterns

Strategy: validation

Validate before calling

// Convert and clamp 1-based UI pages to 0-based indexes
$pageParam = (int) request()->input('page', 1); // 1-based from the UI
$currentPage = max(0, $pageParam - 1);          // 0-based index, never negative
$params = new \Dashboard\Classes\ReportDataPaginationParams($perPage, $currentPage);

Type guard

/**
 * @param mixed $value
 * @returns {boolean}
 */
function isValidPageIndex($value)
{
    return is_int($value) && $value >= 0;
}

Prevention

When it happens

Trigger: Constructing with `(int) get('page') - 1` when the request page is 0 or missing, yielding -1; page inputs that allow negative numbers; arithmetic on page numbers that underflows before the call.

Common situations: Converting 1-based UI page numbers to 0-based indexes and forgetting the floor; defaulting page to -1 as an 'unset' sentinel; tests passing -1.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of octobercms/october@b608633a7e (2026-08-21). Data as JSON: /api/errors/fcce7ff0a30d65cc. Report an issue: GitHub.

Appendix: source

Thrown at modules/backend/assets/foundation/controls/inspector/inspector.surface.js:40

    var Base = $.oc.foundation.base,
        BaseProto = Base.prototype

    /**
     * Creates the Inspector surface in a container.
     * - containerElement container DOM element
     * - properties array (array of objects)
     * - values - property values, an object
     * - inspectorUniqueId - a string containing the unique inspector identifier.
     *   The identifier should be a constant for an inspectable element. Use
     *   $.oc.inspector.helpers.generateElementUniqueId(element) to generate a persistent ID
     *   for an element. Use $.oc.inspector.helpers.generateUniqueId() to generate an ID
     *   not associated with an element. Inspector uses the ID for storing configuration
     *   related to an element in the document DOM.
     */
    var Surface = function(containerElement, properties, values, inspectorUniqueId, options, parentSurface, group, propertyName) {
        if (inspectorUniqueId === undefined) {
            throw new Error('Inspector surface unique ID should be defined.')
        }

        this.options = $.extend({}, Surface.DEFAULTS, typeof options == 'object' && options)
        this.rawProperties = properties
        this.parsedProperties = $.oc.inspector.engine.processPropertyGroups(properties)
        this.container = containerElement
        this.inspectorUniqueId = inspectorUniqueId
        this.values = values !== null ? values : {}
        this.originalValues = $.extend(true, {}, this.values) // Clone the values hash
        this.idCounter = 1
        this.popupCounter = 0
        this.parentSurface = parentSurface
        this.propertyName = propertyName

        this.editors = []
        this.externalParameterEditors = []
        this.tableContainer = null
        this.groupManager = null

View on GitHub (pinned to b608633a7e)